Micron Document
🎖️GitЯра🎖️


Displaying Raw • Download

examples/simple_room_server/MyMesh.cpp HEAD (0679dbef) Text, 41.67 KB

Tff7b72#Tff7b72include T8b949e"MyMesh.h"

Tff7b72#Tff7b72define REPLY_DELAY_MILLIS 1500
Tff7b72#Tff7b72define PUSH_NOTIFY_DELAY_MILLIS 2000
Tff7b72#Tff7b72define SYNC_PUSH_INTERVAL 1200

Tff7b72#Tff7b72define PUSH_ACK_TIMEOUT_FLOOD 12000
Tff7b72#Tff7b72define PUSH_TIMEOUT_BASE 4000
Tff7b72#Tff7b72define PUSH_ACK_TIMEOUT_FACTOR 2000

Tff7b72#Tff7b72define POST_SYNC_DELAY_SECS 6

Tff7b72#Tff7b72define FIRMWARE_VER_LEVEL 1

Tff7b72#Tff7b72define REQ_TYPE_GET_STATUS 0x01 T8b949e// same as _GET_STATS
Tff7b72#Tff7b72define REQ_TYPE_KEEP_ALIVE 0x02
Tff7b72#Tff7b72define REQ_TYPE_GET_TELEMETRY_DATA 0x03
Tff7b72#Tff7b72define REQ_TYPE_GET_ACCESS_LIST 0x05

Tff7b72#Tff7b72define RESP_SERVER_LOGIN_OK 0 T8b949e// response to ANON_REQ

Tff7b72#Tff7b72define LAZY_CONTACTS_WRITE_DELAY 5000

Tff7b72struct T56d364ServerStats Tb4b4b4{
Tffa657uint16_t Te6edf3batt_milli_voltsTb4b4b4;
Tffa657uint16_t Te6edf3curr_tx_queue_lenTb4b4b4;
Tffa657int16_t Te6edf3noise_floorTb4b4b4;
Tffa657int16_t Te6edf3last_rssiTb4b4b4;
Tffa657uint32_t Te6edf3n_packets_recvTb4b4b4;
Tffa657uint32_t Te6edf3n_packets_sentTb4b4b4;
Tffa657uint32_t Te6edf3total_air_time_secsTb4b4b4;
Tffa657uint32_t Te6edf3total_up_time_secsTb4b4b4;
Tffa657uint32_t Te6edf3n_sent_floodTb4b4b4, Te6edf3n_sent_directTb4b4b4;
Tffa657uint32_t Te6edf3n_recv_floodTb4b4b4, Te6edf3n_recv_directTb4b4b4;
Tffa657uint16_t Te6edf3err_eventsTb4b4b4; T8b949e// was 'n_full_events'
Tffa657int16_t Te6edf3last_snrTb4b4b4; T8b949e// x 4
Tffa657uint16_t Te6edf3n_direct_dupsTb4b4b4, Te6edf3n_flood_dupsTb4b4b4;
Tffa657uint16_t Te6edf3n_postedTb4b4b4, Te6edf3n_post_pushTb4b4b4;
Tb4b4b4}Tb4b4b4;

Tffa657void Td2a8ffMyMesh::addPostTb4b4b4(Te6edf3ClientInfo Tff7b72*Te6edf3clientTb4b4b4, Tff7b72const Tffa657char Tff7b72*Te6edf3postDataTb4b4b4) Tb4b4b4{
Te6edf3storePostTb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3idTb4b4b4, Te6edf3postDataTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657void Td2a8ffMyMesh::addSystemPostTb4b4b4(Tff7b72const Tffa657char Tff7b72*Te6edf3postDataTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3postData Tff7b72|Tff7b72| Te6edf3postDataTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tff7b72returnTb4b4b4;

Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffroom.post: addSystemPost: %sTa5d6ff"Tb4b4b4, Te6edf3postDataTb4b4b4)Tb4b4b4;

Te6edf3storePostTb4b4b4(Te6edf3self_idTb4b4b4, Te6edf3postDataTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657void Td2a8ffMyMesh::storePostTb4b4b4(Tff7b72const Te6edf3meshTff7b72:Tff7b72:Te6edf3Identity Tff7b72&Te6edf3authorTb4b4b4, Tff7b72const Tffa657char Tff7b72*Te6edf3postDataTb4b4b4) Tb4b4b4{
Tffa657int Te6edf3idx Tff7b72= Te6edf3next_post_idxTb4b4b4;
T8b949e// TODO: suggested postData format: <title>/<descrption>
Te6edf3postsTb4b4b4[Te6edf3idxTb4b4b4]Tb4b4b4.Te6edf3author Tff7b72= Te6edf3authorTb4b4b4; T8b949e// add to cyclic queue
Te6edf3StrHelperTff7b72:Tff7b72:Te6edf3strncpyTb4b4b4(Te6edf3postsTb4b4b4[Te6edf3idxTb4b4b4]Tb4b4b4.Te6edf3textTb4b4b4, Te6edf3postDataTb4b4b4, Te6edf3MAX_POST_TEXT_LENTb4b4b4)Tb4b4b4;

Te6edf3postsTb4b4b4[Te6edf3idxTb4b4b4]Tb4b4b4.Te6edf3post_timestamp Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeUniqueTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffroom.post: storePost idx=%d text=%sTa5d6ff"Tb4b4b4, Te6edf3idxTb4b4b4, Te6edf3postsTb4b4b4[Te6edf3idxTb4b4b4]Tb4b4b4.Te6edf3textTb4b4b4)Tb4b4b4;
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffroom.post: timestamp=%uTa5d6ff"Tb4b4b4, Te6edf3postsTb4b4b4[Te6edf3idxTb4b4b4]Tb4b4b4.Te6edf3post_timestampTb4b4b4)Tb4b4b4;
Te6edf3next_post_idx Tff7b72= Tb4b4b4(Te6edf3next_post_idx Tff7b72+ T79c0ff1Tb4b4b4) Tff7b72% Te6edf3MAX_UNSYNCED_POSTSTb4b4b4;

Te6edf3next_push Tff7b72= Te6edf3futureMillisTb4b4b4(Te6edf3PUSH_NOTIFY_DELAY_MILLISTb4b4b4)Tb4b4b4;
Te6edf3_num_postedTff7b72+Tff7b72+Tb4b4b4; T8b949e// stats
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffroom.post: next_post_idx=%d num_posted=%d push scheduledTa5d6ff"Tb4b4b4, Te6edf3next_post_idxTb4b4b4, Te6edf3_num_postedTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657void Td2a8ffMyMesh::pushPostToClientTb4b4b4(Te6edf3ClientInfo Tff7b72*Te6edf3clientTb4b4b4, Te6edf3PostInfo Tff7b72&Tff7b72postTb4b4b4) Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffroom.post: pushPostToClient text=%sTa5d6ff"Tb4b4b4, Tff7b72postTb4b4b4.Te6edf3textTb4b4b4)Tb4b4b4;
Tffa657int Te6edf3len Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[Te6edf3lenTb4b4b4]Tb4b4b4, Tff7b72&Tff7b72postTb4b4b4.Te6edf3post_timestampTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4;
Te6edf3len Tff7b72+Tff7b72= T79c0ff4Tb4b4b4; T8b949e// this is a PAST timestamp... but should be accepted by client

Tffa657uint8_t Te6edf3attemptTb4b4b4;
Te6edf3getRNGTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3randomTb4b4b4(Tff7b72&Te6edf3attemptTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4; T8b949e// need this for re-tries, so packet hash (and ACK) will be different
Te6edf3reply_dataTb4b4b4[Te6edf3lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Tb4b4b4(Te6edf3TXT_TYPE_SIGNED_PLAIN Tff7b72<Tff7b72< T79c0ff2Tb4b4b4) Tff7b72| Tb4b4b4(Te6edf3attempt Tff7b72& T79c0ff3Tb4b4b4)Tb4b4b4; T8b949e// 'signed' plain text

T8b949e// encode prefix of post.author.pub_key
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[Te6edf3lenTb4b4b4]Tb4b4b4, Tff7b72postTb4b4b4.Te6edf3authorTb4b4b4.Te6edf3pub_keyTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4;
Te6edf3len Tff7b72+Tff7b72= T79c0ff4Tb4b4b4; T8b949e// just first 4 bytes

Tffa657int Te6edf3text_len Tff7b72= Te6edf3strlenTb4b4b4(Tff7b72postTb4b4b4.Te6edf3textTb4b4b4)Tb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[Te6edf3lenTb4b4b4]Tb4b4b4, Tff7b72postTb4b4b4.Te6edf3textTb4b4b4, Te6edf3text_lenTb4b4b4)Tb4b4b4;
Te6edf3len Tff7b72+Tff7b72= Te6edf3text_lenTb4b4b4;

T8b949e// calc expected ACK reply
Te6edf3meshTff7b72:Tff7b72:Te6edf3UtilsTff7b72:Tff7b72:Te6edf3sha256Tb4b4b4(Tb4b4b4(Tffa657uint8_t Tff7b72*Tb4b4b4)Tff7b72&Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3pending_ackTb4b4b4, T79c0ff4Tb4b4b4, Te6edf3reply_dataTb4b4b4, Te6edf3lenTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3idTb4b4b4.Te6edf3pub_keyTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3push_post_timestamp Tff7b72= Tff7b72postTb4b4b4.Te6edf3post_timestampTb4b4b4;

Tff7b72auto Te6edf3reply Tff7b72= Te6edf3createDatagramTb4b4b4(Te6edf3PAYLOAD_TYPE_TXT_MSGTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3idTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3shared_secretTb4b4b4, Te6edf3reply_dataTb4b4b4, Te6edf3lenTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3replyTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72=Tff7b72= Te6edf3OUT_PATH_UNKNOWNTb4b4b4) Tb4b4b4{
Tffa657unsigned Tffa657long Te6edf3delay_millis Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3sendFloodScopedTb4b4b4(Te6edf3default_scopeTb4b4b4, Te6edf3replyTb4b4b4, Te6edf3delay_millisTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3path_hash_mode Tff7b72+ T79c0ff1Tb4b4b4)Tb4b4b4; T8b949e// REVISIT
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3ack_timeout Tff7b72= Te6edf3futureMillisTb4b4b4(Te6edf3PUSH_ACK_TIMEOUT_FLOODTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3sendDirectTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_pathTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_lenTb4b4b4)Tb4b4b4;

Tffa657uint8_t Te6edf3path_hash_count Tff7b72= Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72& T79c0ff63Tb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3ack_timeout Tff7b72= Te6edf3futureMillisTb4b4b4(Te6edf3PUSH_TIMEOUT_BASE Tff7b72+ Te6edf3PUSH_ACK_TIMEOUT_FACTOR Tff7b72* Tb4b4b4(Te6edf3path_hash_count Tff7b72+ T79c0ff1Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3_num_post_pushesTff7b72+Tff7b72+Tb4b4b4; T8b949e// stats
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3pending_ack Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffUnable to push post to clientTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tffa657uint8_t Td2a8ffMyMesh::getUnsyncedCountTb4b4b4(Te6edf3ClientInfo Tff7b72*Te6edf3clientTb4b4b4) Tb4b4b4{
Tffa657uint8_t Te6edf3count Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tffa657int Te6edf3k Tff7b72= T79c0ff0Tb4b4b4; Te6edf3k Tff7b72< Te6edf3MAX_UNSYNCED_POSTSTb4b4b4; Te6edf3kTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3postsTb4b4b4[Te6edf3kTb4b4b4]Tb4b4b4.Te6edf3post_timestamp Tff7b72> Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3sync_since T8b949e// is new post for this Client?
Tff7b72&Tff7b72& Tff7b72!Te6edf3postsTb4b4b4[Te6edf3kTb4b4b4]Tb4b4b4.Te6edf3authorTb4b4b4.Te6edf3matchesTb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3idTb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// don't push posts to the author
Te6edf3countTff7b72+Tff7b72+Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3countTb4b4b4;
Tb4b4b4}

Tffa657bool Td2a8ffMyMesh::processAckTb4b4b4(Tff7b72const Tffa657uint8_t Tff7b72*Te6edf3dataTb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tffa657int Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3client Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3pending_ack Tff7b72&Tff7b72& Te6edf3memcmpTb4b4b4(Te6edf3dataTb4b4b4, Tff7b72&Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3pending_ackTb4b4b4, T79c0ff4Tb4b4b4) Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// got an ACK from Client!
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3pending_ack Tff7b72= T79c0ff0Tb4b4b4; T8b949e// clear this, so next push can happen
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3push_failures Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3sync_since Tff7b72= Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3push_post_timestampTb4b4b4; T8b949e// advance Client's SINCE timestamp, to sync next post
Tff7b72return Tffa657trueTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}

Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Td2a8ffMyMesh::createSelfAdvertTb4b4b4(Tb4b4b4) Tb4b4b4{
Tffa657uint8_t Te6edf3app_dataTb4b4b4[Te6edf3MAX_ADVERT_DATA_SIZETb4b4b4]Tb4b4b4;
Tffa657uint8_t Te6edf3app_data_len Tff7b72= Te6edf3_cliTb4b4b4.Te6edf3buildAdvertDataTb4b4b4(Te6edf3ADV_TYPE_ROOMTb4b4b4, Te6edf3app_dataTb4b4b4)Tb4b4b4;

Tff7b72return Te6edf3createAdvertTb4b4b4(Te6edf3self_idTb4b4b4, Te6edf3app_dataTb4b4b4, Te6edf3app_data_lenTb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3File Td2a8ffMyMesh::openAppendTb4b4b4(Tff7b72const Tffa657char Tff7b72*Te6edf3fnameTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if defined(NRF52_PLATFORM)
Tff7b72return Te6edf3_fsTff7b72-Tff7b72>Te6edf3openTb4b4b4(Te6edf3fnameTb4b4b4, Te6edf3FILE_O_WRITETb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif defined(RP2040_PLATFORM)
Tff7b72return Te6edf3_fsTff7b72-Tff7b72>Te6edf3openTb4b4b4(Te6edf3fnameTb4b4b4, Ta5d6ff"Ta5d6ffaTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72return Te6edf3_fsTff7b72-Tff7b72>Te6edf3openTb4b4b4(Te6edf3fnameTb4b4b4, Ta5d6ff"Ta5d6ffaTa5d6ff"Tb4b4b4, Tffa657trueTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

Tffa657int Td2a8ffMyMesh::handleRequestTb4b4b4(Te6edf3ClientInfo Tff7b72*Te6edf3senderTb4b4b4, Tffa657uint32_t Te6edf3sender_timestampTb4b4b4, Tffa657uint8_t Tff7b72*Te6edf3payloadTb4b4b4,
Tffa657size_t Te6edf3payload_lenTb4b4b4) Tb4b4b4{
T8b949e// uint32_t now = getRTCClock()->getCurrentTimeUnique();
T8b949e// memcpy(reply_data, &now, 4); // response packets always prefixed with timestamp
Te6edf3memcpyTb4b4b4(Te6edf3reply_dataTb4b4b4, Tff7b72&Te6edf3sender_timestampTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// reflect sender_timestamp back in response packet (kind of like a 'tag')

Tff7b72if Tb4b4b4(Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=Tff7b72= Te6edf3REQ_TYPE_GET_STATUSTb4b4b4) Tb4b4b4{
Te6edf3ServerStats Te6edf3statsTb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3batt_milli_volts Tff7b72= Te6edf3boardTb4b4b4.Te6edf3getBattMilliVoltsTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3curr_tx_queue_len Tff7b72= Te6edf3_mgrTff7b72-Tff7b72>Te6edf3getOutboundTotalTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3noise_floor Tff7b72= Tb4b4b4(Tffa657int16_tTb4b4b4)Te6edf3_radioTff7b72-Tff7b72>Te6edf3getNoiseFloorTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3last_rssi Tff7b72= Tb4b4b4(Tffa657int16_tTb4b4b4)Te6edf3radio_driverTb4b4b4.Te6edf3getLastRSSITb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3n_packets_recv Tff7b72= Te6edf3radio_driverTb4b4b4.Te6edf3getPacketsRecvTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3n_packets_sent Tff7b72= Te6edf3radio_driverTb4b4b4.Te6edf3getPacketsSentTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3total_air_time_secs Tff7b72= Te6edf3getTotalAirTimeTb4b4b4(Tb4b4b4) Tff7b72/ T79c0ff1000Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3total_up_time_secs Tff7b72= Te6edf3uptime_millis Tff7b72/ T79c0ff1000Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3n_sent_flood Tff7b72= Te6edf3getNumSentFloodTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3n_sent_direct Tff7b72= Te6edf3getNumSentDirectTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3n_recv_flood Tff7b72= Te6edf3getNumRecvFloodTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3n_recv_direct Tff7b72= Te6edf3getNumRecvDirectTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3err_events Tff7b72= Te6edf3_err_flagsTb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3last_snr Tff7b72= Tb4b4b4(Tffa657int16_tTb4b4b4)Tb4b4b4(Te6edf3radio_driverTb4b4b4.Te6edf3getLastSNRTb4b4b4(Tb4b4b4) Tff7b72* T79c0ff4Tb4b4b4)Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3n_direct_dups Tff7b72= Tb4b4b4(Tb4b4b4(Te6edf3SimpleMeshTables Tff7b72*Tb4b4b4)Te6edf3getTablesTb4b4b4(Tb4b4b4)Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getNumDirectDupsTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3n_flood_dups Tff7b72= Tb4b4b4(Tb4b4b4(Te6edf3SimpleMeshTables Tff7b72*Tb4b4b4)Te6edf3getTablesTb4b4b4(Tb4b4b4)Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getNumFloodDupsTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3n_posted Tff7b72= Te6edf3_num_postedTb4b4b4;
Te6edf3statsTb4b4b4.Te6edf3n_post_push Tff7b72= Te6edf3_num_post_pushesTb4b4b4;

Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4, Tff7b72&Te6edf3statsTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3statsTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72return T79c0ff4 Tff7b72+ Tff7b72sizeofTb4b4b4(Te6edf3statsTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=Tff7b72= Te6edf3REQ_TYPE_GET_TELEMETRY_DATATb4b4b4) Tb4b4b4{
Tffa657uint8_t Te6edf3perm_mask Tff7b72= Tff7b72~Tb4b4b4(Te6edf3payloadTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4)Tb4b4b4; T8b949e// NEW: first reserved byte (of 4), is now inverse mask to apply to permissions

Te6edf3telemetryTb4b4b4.Te6edf3resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3telemetryTb4b4b4.Te6edf3addVoltageTb4b4b4(Te6edf3TELEM_CHANNEL_SELFTb4b4b4, Tb4b4b4(Tffa657floatTb4b4b4)Te6edf3boardTb4b4b4.Te6edf3getBattMilliVoltsTb4b4b4(Tb4b4b4) Tff7b72/ T79c0ff1000.0fTb4b4b4)Tb4b4b4;
T8b949e// query other sensors -- target specific
Tff7b72if Tb4b4b4(Tb4b4b4(Te6edf3senderTff7b72-Tff7b72>Te6edf3permissions Tff7b72& Te6edf3PERM_ACL_ROLE_MASKTb4b4b4) Tff7b72=Tff7b72= Te6edf3PERM_ACL_GUESTTb4b4b4) Tb4b4b4{
Te6edf3perm_mask Tff7b72= T79c0ff0x00Tb4b4b4; T8b949e// just base telemetry allowed
Tb4b4b4}
Te6edf3sensorsTb4b4b4.Te6edf3querySensorsTb4b4b4(Te6edf3perm_maskTb4b4b4, Te6edf3telemetryTb4b4b4)Tb4b4b4;

T8b949e// This default temperature will be overridden by external sensors (if any)
Tffa657float Te6edf3temperature Tff7b72= Te6edf3boardTb4b4b4.Te6edf3getMCUTemperatureTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72ifTb4b4b4(Tff7b72!Te6edf3isnanTb4b4b4(Te6edf3temperatureTb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// Supported boards with built-in temperature sensor. ESP32-C3 may return NAN
Te6edf3telemetryTb4b4b4.Te6edf3addTemperatureTb4b4b4(Te6edf3TELEM_CHANNEL_SELFTb4b4b4, Te6edf3temperatureTb4b4b4)Tb4b4b4; T8b949e// Built-in MCU Temperature
Tb4b4b4}

Tffa657uint8_t Te6edf3tlen Tff7b72= Te6edf3telemetryTb4b4b4.Te6edf3getSizeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4, Te6edf3telemetryTb4b4b4.Te6edf3getBufferTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3tlenTb4b4b4)Tb4b4b4;
Tff7b72return T79c0ff4 Tff7b72+ Te6edf3tlenTb4b4b4; T8b949e// reply_len
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=Tff7b72= Te6edf3REQ_TYPE_GET_ACCESS_LIST Tff7b72&Tff7b72& Te6edf3senderTff7b72-Tff7b72>Te6edf3isAdminTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tffa657uint8_t Te6edf3res1 Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4; T8b949e// reserved for future (extra query params)
Tffa657uint8_t Te6edf3res2 Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3res1 Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3res2 Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Tffa657uint8_t Te6edf3ofs Tff7b72= T79c0ff4Tb4b4b4;
Tff7b72for Tb4b4b4(Tffa657int Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3ofs Tff7b72+ T79c0ff7 Tff7b72<Tff7b72= Tff7b72sizeofTb4b4b4(Te6edf3reply_dataTb4b4b4) Tff7b72- T79c0ff4Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3c Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3cTff7b72-Tff7b72>Te6edf3isAdminTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72continueTb4b4b4; T8b949e// skip non-Admin entries
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[Te6edf3ofsTb4b4b4]Tb4b4b4, Te6edf3cTff7b72-Tff7b72>Te6edf3idTb4b4b4.Te6edf3pub_keyTb4b4b4, T79c0ff6Tb4b4b4)Tb4b4b4; Te6edf3ofs Tff7b72+Tff7b72= T79c0ff6Tb4b4b4; T8b949e// just 6-byte pub_key prefix
Te6edf3reply_dataTb4b4b4[Te6edf3ofsTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3cTff7b72-Tff7b72>Te6edf3permissionsTb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3ofsTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72return T79c0ff0Tb4b4b4; T8b949e// unknown command
Tb4b4b4}

Tffa657void Td2a8ffMyMesh::logRxRawTb4b4b4(Tffa657float Te6edf3snrTb4b4b4, Tffa657float Te6edf3rssiTb4b4b4, Tff7b72const Tffa657uint8_t Te6edf3rawTb4b4b4[Tb4b4b4]Tb4b4b4, Tffa657int Te6edf3lenTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MESH_PACKET_LOGGING
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Te6edf3getLogDateTimeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Ta5d6ff"Ta5d6ff RAW: Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3meshTff7b72:Tff7b72:Te6edf3UtilsTff7b72:Tff7b72:Te6edf3printHexTb4b4b4(Te6edf3SerialTb4b4b4, Te6edf3rawTb4b4b4, Te6edf3lenTb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

Tffa657void Td2a8ffMyMesh::logRxTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3pktTb4b4b4, Tffa657int Te6edf3lenTb4b4b4, Tffa657float Te6edf3scoreTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_loggingTb4b4b4) Tb4b4b4{
Te6edf3File Te6edf3f Tff7b72= Te6edf3openAppendTb4b4b4(Te6edf3PACKET_LOG_FILETb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4) Tb4b4b4{
Te6edf3fTb4b4b4.Te6edf3printTb4b4b4(Te6edf3getLogDateTimeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff: RX, len=%d (type=%d, route=%s, payload_len=%d) SNR=%d RSSI=%d score=%dTa5d6ff"Tb4b4b4, Te6edf3lenTb4b4b4,
Te6edf3pktTff7b72-Tff7b72>Te6edf3getPayloadTypeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3pktTff7b72-Tff7b72>Te6edf3isRouteDirectTb4b4b4(Tb4b4b4) Tff7b72? Ta5d6ff"Ta5d6ffDTa5d6ff" Tff7b72: Ta5d6ff"Ta5d6ffFTa5d6ff"Tb4b4b4, Te6edf3pktTff7b72-Tff7b72>Te6edf3payload_lenTb4b4b4,
Tb4b4b4(Tffa657intTb4b4b4)Te6edf3_radioTff7b72-Tff7b72>Te6edf3getLastSNRTb4b4b4(Tb4b4b4)Tb4b4b4, Tb4b4b4(Tffa657intTb4b4b4)Te6edf3_radioTff7b72-Tff7b72>Te6edf3getLastRSSITb4b4b4(Tb4b4b4)Tb4b4b4, Tb4b4b4(Tffa657intTb4b4b4)Tb4b4b4(Te6edf3score Tff7b72* T79c0ff1000Tb4b4b4)Tb4b4b4)Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3pktTff7b72-Tff7b72>Te6edf3getPayloadTypeTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_PATH Tff7b72|Tff7b72| Te6edf3pktTff7b72-Tff7b72>Te6edf3getPayloadTypeTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_REQ Tff7b72|Tff7b72|
Te6edf3pktTff7b72-Tff7b72>Te6edf3getPayloadTypeTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_RESPONSE Tff7b72|Tff7b72| Te6edf3pktTff7b72-Tff7b72>Te6edf3getPayloadTypeTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_TXT_MSGTb4b4b4) Tb4b4b4{
Te6edf3fTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff [%02X -> %02X]Tffea00\nTa5d6ff"Tb4b4b4, Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3pktTff7b72-Tff7b72>Te6edf3payloadTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4, Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3pktTff7b72-Tff7b72>Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3fTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3fTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tffa657void Td2a8ffMyMesh::logTxTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3pktTb4b4b4, Tffa657int Te6edf3lenTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_loggingTb4b4b4) Tb4b4b4{
Te6edf3File Te6edf3f Tff7b72= Te6edf3openAppendTb4b4b4(Te6edf3PACKET_LOG_FILETb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4) Tb4b4b4{
Te6edf3fTb4b4b4.Te6edf3printTb4b4b4(Te6edf3getLogDateTimeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff: TX, len=%d (type=%d, route=%s, payload_len=%d)Ta5d6ff"Tb4b4b4, Te6edf3lenTb4b4b4, Te6edf3pktTff7b72-Tff7b72>Te6edf3getPayloadTypeTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3pktTff7b72-Tff7b72>Te6edf3isRouteDirectTb4b4b4(Tb4b4b4) Tff7b72? Ta5d6ff"Ta5d6ffDTa5d6ff" Tff7b72: Ta5d6ff"Ta5d6ffFTa5d6ff"Tb4b4b4, Te6edf3pktTff7b72-Tff7b72>Te6edf3payload_lenTb4b4b4)Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3pktTff7b72-Tff7b72>Te6edf3getPayloadTypeTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_PATH Tff7b72|Tff7b72| Te6edf3pktTff7b72-Tff7b72>Te6edf3getPayloadTypeTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_REQ Tff7b72|Tff7b72|
Te6edf3pktTff7b72-Tff7b72>Te6edf3getPayloadTypeTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_RESPONSE Tff7b72|Tff7b72| Te6edf3pktTff7b72-Tff7b72>Te6edf3getPayloadTypeTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_TXT_MSGTb4b4b4) Tb4b4b4{
Te6edf3fTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff [%02X -> %02X]Tffea00\nTa5d6ff"Tb4b4b4, Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3pktTff7b72-Tff7b72>Te6edf3payloadTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4, Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3pktTff7b72-Tff7b72>Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3fTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3fTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tffa657void Td2a8ffMyMesh::logTxFailTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3pktTb4b4b4, Tffa657int Te6edf3lenTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_loggingTb4b4b4) Tb4b4b4{
Te6edf3File Te6edf3f Tff7b72= Te6edf3openAppendTb4b4b4(Te6edf3PACKET_LOG_FILETb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4) Tb4b4b4{
Te6edf3fTb4b4b4.Te6edf3printTb4b4b4(Te6edf3getLogDateTimeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff: TX FAIL!, len=%d (type=%d, route=%s, payload_len=%d)Tffea00\nTa5d6ff"Tb4b4b4, Te6edf3lenTb4b4b4, Te6edf3pktTff7b72-Tff7b72>Te6edf3getPayloadTypeTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3pktTff7b72-Tff7b72>Te6edf3isRouteDirectTb4b4b4(Tb4b4b4) Tff7b72? Ta5d6ff"Ta5d6ffDTa5d6ff" Tff7b72: Ta5d6ff"Ta5d6ffFTa5d6ff"Tb4b4b4, Te6edf3pktTff7b72-Tff7b72>Te6edf3payload_lenTb4b4b4)Tb4b4b4;
Te6edf3fTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tffa657int Td2a8ffMyMesh::calcRxDelayTb4b4b4(Tffa657float Te6edf3scoreTb4b4b4, Tffa657uint32_t Te6edf3air_timeTb4b4b4) Tff7b72const Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3rx_delay_base Tff7b72<Tff7b72= T79c0ff0.0fTb4b4b4) Tff7b72return T79c0ff0Tb4b4b4;
Tff7b72return Tb4b4b4(Tffa657intTb4b4b4)Tb4b4b4(Tb4b4b4(Te6edf3powTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3rx_delay_baseTb4b4b4, T79c0ff0.85f Tff7b72- Te6edf3scoreTb4b4b4) Tff7b72- T79c0ff1.0Tb4b4b4) Tff7b72* Te6edf3air_timeTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72const Tffa657char Tff7b72*Td2a8ffMyMesh::getLogDateTimeTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72static Tffa657char Te6edf3tmpTb4b4b4[T79c0ff32Tb4b4b4]Tb4b4b4;
Tffa657uint32_t Te6edf3now Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3DateTime Te6edf3dt Tff7b72= Te6edf3DateTimeTb4b4b4(Te6edf3nowTb4b4b4)Tb4b4b4;
Te6edf3sprintfTb4b4b4(Te6edf3tmpTb4b4b4, Ta5d6ff"Ta5d6ff%02d:%02d:%02d - %d/%d/%d UTa5d6ff"Tb4b4b4, Te6edf3dtTb4b4b4.Te6edf3hourTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3dtTb4b4b4.Te6edf3minuteTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3dtTb4b4b4.Te6edf3secondTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3dtTb4b4b4.Te6edf3dayTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3dtTb4b4b4.Te6edf3monthTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3dtTb4b4b4.Te6edf3yearTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3tmpTb4b4b4;
Tb4b4b4}

Tffa657uint32_t Td2a8ffMyMesh::getRetransmitDelayTb4b4b4(Tff7b72const Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3packetTb4b4b4) Tb4b4b4{
Tffa657uint32_t Te6edf3t Tff7b72= Tb4b4b4(Te6edf3_radioTff7b72-Tff7b72>Te6edf3getEstAirtimeForTb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathByteLenTb4b4b4(Tb4b4b4) Tff7b72+ Te6edf3packetTff7b72-Tff7b72>Te6edf3payload_len Tff7b72+ T79c0ff2Tb4b4b4) Tff7b72* Te6edf3_prefsTb4b4b4.Te6edf3tx_delay_factorTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3getRNGTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3nextIntTb4b4b4(T79c0ff0Tb4b4b4, T79c0ff5Tff7b72*Te6edf3t Tff7b72+ T79c0ff1Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tffa657uint32_t Td2a8ffMyMesh::getDirectRetransmitDelayTb4b4b4(Tff7b72const Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3packetTb4b4b4) Tb4b4b4{
Tffa657uint32_t Te6edf3t Tff7b72= Tb4b4b4(Te6edf3_radioTff7b72-Tff7b72>Te6edf3getEstAirtimeForTb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathByteLenTb4b4b4(Tb4b4b4) Tff7b72+ Te6edf3packetTff7b72-Tff7b72>Te6edf3payload_len Tff7b72+ T79c0ff2Tb4b4b4) Tff7b72* Te6edf3_prefsTb4b4b4.Te6edf3direct_tx_delay_factorTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3getRNGTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3nextIntTb4b4b4(T79c0ff0Tb4b4b4, T79c0ff5Tff7b72*Te6edf3t Tff7b72+ T79c0ff1Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657bool Td2a8ffMyMesh::allowPacketForwardTb4b4b4(Tff7b72const Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3packetTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3disable_fwdTb4b4b4) Tff7b72return Tffa657falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3isRouteFloodTb4b4b4(Tb4b4b4)
Tff7b72&Tff7b72& Te6edf3meshTff7b72:Tff7b72:Te6edf3isFloodHopLimitExceededTb4b4b4(Te6edf3packetTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3flood_maxTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3flood_max_unscopedTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3flood_max_advertTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Tff7b72return Tffa657trueTb4b4b4;
Tb4b4b4}

Te6edf3meshTff7b72:Tff7b72:Te6edf3DispatcherAction Td2a8ffMyMesh::onRecvPacketTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3pktTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3pktTff7b72-Tff7b72>Te6edf3getRouteTypeTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3ROUTE_TYPE_TRANSPORT_FLOODTb4b4b4) Tb4b4b4{
Te6edf3recv_pkt_region Tff7b72= Te6edf3region_mapTb4b4b4.Te6edf3findMatchTb4b4b4(Te6edf3pktTb4b4b4, Te6edf3REGION_DENY_FLOODTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3pktTff7b72-Tff7b72>Te6edf3getRouteTypeTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3ROUTE_TYPE_FLOODTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3region_mapTb4b4b4.Te6edf3getWildcardTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3flags Tff7b72& Te6edf3REGION_DENY_FLOODTb4b4b4) Tb4b4b4{
Te6edf3recv_pkt_region Tff7b72= Tffa657NULLTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3recv_pkt_region Tff7b72= Tff7b72&Te6edf3region_mapTb4b4b4.Te6edf3getWildcardTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3recv_pkt_region Tff7b72= Tffa657NULLTb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3MeshTff7b72:Tff7b72:Te6edf3onRecvPacketTb4b4b4(Te6edf3pktTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657void Td2a8ffMyMesh::onAnonDataRecvTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3packetTb4b4b4, Tff7b72const Tffa657uint8_t Tff7b72*Te6edf3secretTb4b4b4, Tff7b72const Te6edf3meshTff7b72:Tff7b72:Te6edf3Identity Tff7b72&Te6edf3senderTb4b4b4,
Tffa657uint8_t Tff7b72*Te6edf3dataTb4b4b4, Tffa657size_t Te6edf3lenTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3getPayloadTypeTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_ANON_REQTb4b4b4) Tb4b4b4{ T8b949e// received an initial request by a possible admin
T8b949e// client (unknown at this stage)
Tffa657uint32_t Te6edf3sender_timestampTb4b4b4, Te6edf3sender_sync_sinceTb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3sender_timestampTb4b4b4, Te6edf3dataTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3sender_sync_sinceTb4b4b4, Tff7b72&Te6edf3dataTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// sender's "sync messags SINCE x" timestamp

Te6edf3dataTb4b4b4[Te6edf3lenTb4b4b4] Tff7b72= T79c0ff0Tb4b4b4; T8b949e// ensure null terminator

Te6edf3ClientInfoTff7b72* Te6edf3client Tff7b72= Tffa657NULLTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3dataTb4b4b4[T79c0ff8Tb4b4b4] Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// blank password, just check if sender is in ACL
Te6edf3client Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientTb4b4b4(Te6edf3senderTb4b4b4.Te6edf3pub_keyTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3client Tff7b72=Tff7b72= Tffa657NULLTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MESH_DEBUG
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffLogin, sender not in ACLTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3client Tff7b72=Tff7b72= Tffa657NULLTb4b4b4) Tb4b4b4{
Tffa657uint8_t Te6edf3permTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3strcmpTb4b4b4(Tb4b4b4(Tffa657char Tff7b72*Tb4b4b4)Tff7b72&Te6edf3dataTb4b4b4[T79c0ff8Tb4b4b4]Tb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3passwordTb4b4b4) Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// check for valid admin password
Te6edf3perm Tff7b72= Te6edf3PERM_ACL_ADMINTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3strcmpTb4b4b4(Tb4b4b4(Tffa657char Tff7b72*Tb4b4b4)Tff7b72&Te6edf3dataTb4b4b4[T79c0ff8Tb4b4b4]Tb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3guest_passwordTb4b4b4) Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// check the room/public password
Te6edf3perm Tff7b72= Te6edf3PERM_ACL_READ_WRITETb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3allow_read_onlyTb4b4b4) Tb4b4b4{
Te6edf3perm Tff7b72= Te6edf3PERM_ACL_GUESTTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffIncorrect room passwordTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4; T8b949e// no response. Client will timeout
Tb4b4b4}
Tb4b4b4}

Te6edf3client Tff7b72= Te6edf3aclTb4b4b4.Te6edf3putClientTb4b4b4(Te6edf3senderTb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4; T8b949e// add to known clients (if not already known)
Tff7b72if Tb4b4b4(Te6edf3sender_timestamp Tff7b72<Tff7b72= Te6edf3clientTff7b72-Tff7b72>Te6edf3last_timestampTb4b4b4) Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffpossible replay attack!Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}

Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffLogin success!Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3last_timestamp Tff7b72= Te6edf3sender_timestampTb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3sync_since Tff7b72= Te6edf3sender_sync_sinceTb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3pending_ack Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3push_failures Tff7b72= T79c0ff0Tb4b4b4;

Te6edf3clientTff7b72-Tff7b72>Te6edf3last_activity Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3permissions Tff7b72&Tff7b72= Tff7b72~T79c0ff0x03Tb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3permissions Tff7b72|Tff7b72= Te6edf3permTb4b4b4;
Te6edf3memcpyTb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3shared_secretTb4b4b4, Te6edf3secretTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;

Te6edf3dirty_contacts_expiry Tff7b72= Te6edf3futureMillisTb4b4b4(Te6edf3LAZY_CONTACTS_WRITE_DELAYTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3isRouteFloodTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72= Te6edf3OUT_PATH_UNKNOWNTb4b4b4; T8b949e// need to rediscover out_path
Tb4b4b4}

Tffa657uint32_t Te6edf3now Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeUniqueTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3memcpyTb4b4b4(Te6edf3reply_dataTb4b4b4, Tff7b72&Te6edf3nowTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// response packets always prefixed with timestamp
T8b949e// TODO: maybe reply with count of messages waiting to be synced for THIS client?
Te6edf3reply_dataTb4b4b4[T79c0ff4Tb4b4b4] Tff7b72= Te6edf3RESP_SERVER_LOGIN_OKTb4b4b4;
Te6edf3reply_dataTb4b4b4[T79c0ff5Tb4b4b4] Tff7b72= T79c0ff0Tb4b4b4; T8b949e// Legacy: was recommended keep-alive interval (secs / 16)
Te6edf3reply_dataTb4b4b4[T79c0ff6Tb4b4b4] Tff7b72= Tb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3isAdminTb4b4b4(Tb4b4b4) Tff7b72? T79c0ff1 Tff7b72: Tb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3permissions Tff7b72=Tff7b72= T79c0ff0 Tff7b72? T79c0ff2 Tff7b72: T79c0ff0Tb4b4b4)Tb4b4b4)Tb4b4b4;
T8b949e// LEGACY: reply_data[7] = getUnsyncedCount(client);
Te6edf3reply_dataTb4b4b4[T79c0ff7Tb4b4b4] Tff7b72= Te6edf3clientTff7b72-Tff7b72>Te6edf3permissionsTb4b4b4; T8b949e// NEW
Te6edf3getRNGTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3randomTb4b4b4(Tff7b72&Te6edf3reply_dataTb4b4b4[T79c0ff8Tb4b4b4]Tb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// random blob to help packet-hash uniqueness
Te6edf3reply_dataTb4b4b4[T79c0ff12Tb4b4b4] Tff7b72= Te6edf3FIRMWARE_VER_LEVELTb4b4b4; T8b949e// New field

Te6edf3next_push Tff7b72= Te6edf3futureMillisTb4b4b4(Te6edf3PUSH_NOTIFY_DELAY_MILLISTb4b4b4)Tb4b4b4; T8b949e// delay next push, give RESPONSE packet time to arrive first

Tff7b72if Tb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3isRouteFloodTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3path Tff7b72= Te6edf3createPathReturnTb4b4b4(Te6edf3senderTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3shared_secretTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3pathTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3path_lenTb4b4b4,
Te6edf3PAYLOAD_TYPE_RESPONSETb4b4b4, Te6edf3reply_dataTb4b4b4, T79c0ff13Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pathTb4b4b4) Te6edf3sendFloodReplyTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3SERVER_RESPONSE_DELAYTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3reply Tff7b72= Te6edf3createDatagramTb4b4b4(Te6edf3PAYLOAD_TYPE_RESPONSETb4b4b4, Te6edf3senderTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3shared_secretTb4b4b4, Te6edf3reply_dataTb4b4b4, T79c0ff13Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3replyTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72!Tff7b72= Te6edf3OUT_PATH_UNKNOWNTb4b4b4) Tb4b4b4{ T8b949e// we have an out_path, so send DIRECT
Te6edf3sendDirectTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_pathTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_lenTb4b4b4, Te6edf3SERVER_RESPONSE_DELAYTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3sendFloodReplyTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3SERVER_RESPONSE_DELAYTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tffa657int Td2a8ffMyMesh::searchPeersByHashTb4b4b4(Tff7b72const Tffa657uint8_t Tff7b72*Te6edf3hashTb4b4b4) Tb4b4b4{
Tffa657int Te6edf3n Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tffa657int Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tff7b72-Tff7b72>Te6edf3idTb4b4b4.Te6edf3isHashMatchTb4b4b4(Te6edf3hashTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3matching_peer_indexesTb4b4b4[Te6edf3nTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3iTb4b4b4; T8b949e// store the INDEXES of matching contacts (for subsequent 'peer' methods)
Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3nTb4b4b4;
Tb4b4b4}

Tffa657void Td2a8ffMyMesh::getPeerSharedSecretTb4b4b4(Tffa657uint8_t Tff7b72*Te6edf3dest_secretTb4b4b4, Tffa657int Te6edf3peer_idxTb4b4b4) Tb4b4b4{
Tffa657int Te6edf3i Tff7b72= Te6edf3matching_peer_indexesTb4b4b4[Te6edf3peer_idxTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3i Tff7b72>Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3i Tff7b72< Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// lookup pre-calculated shared_secret
Te6edf3memcpyTb4b4b4(Te6edf3dest_secretTb4b4b4, Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tff7b72-Tff7b72>Te6edf3shared_secretTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffgetPeerSharedSecret: Invalid peer idx: %dTa5d6ff"Tb4b4b4, Te6edf3iTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tffa657void Td2a8ffMyMesh::onPeerDataRecvTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3packetTb4b4b4, Tffa657uint8_t Te6edf3typeTb4b4b4, Tffa657int Te6edf3sender_idxTb4b4b4, Tff7b72const Tffa657uint8_t Tff7b72*Te6edf3secretTb4b4b4,
Tffa657uint8_t Tff7b72*Te6edf3dataTb4b4b4, Tffa657size_t Te6edf3lenTb4b4b4) Tb4b4b4{
Tffa657int Te6edf3i Tff7b72= Te6edf3matching_peer_indexesTb4b4b4[Te6edf3sender_idxTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3i Tff7b72< T79c0ff0 Tff7b72|Tff7b72| Te6edf3i Tff7b72>Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// get from our known_clients table (sender SHOULD already be known in this context)
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffonPeerDataRecv: invalid peer idx: %dTa5d6ff"Tb4b4b4, Te6edf3iTb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72auto Te6edf3client Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3type Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_TXT_MSG Tff7b72&Tff7b72& Te6edf3len Tff7b72> T79c0ff5Tb4b4b4) Tb4b4b4{ T8b949e// a CLI command or new Post
Tffa657uint32_t Te6edf3sender_timestampTb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3sender_timestampTb4b4b4, Te6edf3dataTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// timestamp (by sender's RTC clock - which could be wrong)
Tffa657uint8_t Te6edf3flags Tff7b72= Tb4b4b4(Te6edf3dataTb4b4b4[T79c0ff4Tb4b4b4] Tff7b72>Tff7b72> T79c0ff2Tb4b4b4)Tb4b4b4; T8b949e// message attempt number, and other flags

Tff7b72if Tb4b4b4(Tff7b72!Tb4b4b4(Te6edf3flags Tff7b72=Tff7b72= Te6edf3TXT_TYPE_PLAIN Tff7b72|Tff7b72| Te6edf3flags Tff7b72=Tff7b72= Te6edf3TXT_TYPE_CLI_DATATb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffonPeerDataRecv: unsupported command flags received: flags=%02xTa5d6ff"Tb4b4b4, Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3flagsTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sender_timestamp Tff7b72>Tff7b72= Te6edf3clientTff7b72-Tff7b72>Te6edf3last_timestampTb4b4b4) Tb4b4b4{ T8b949e// prevent replay attacks, but send Acks for retries
Tffa657bool Te6edf3is_retry Tff7b72= Tb4b4b4(Te6edf3sender_timestamp Tff7b72=Tff7b72= Te6edf3clientTff7b72-Tff7b72>Te6edf3last_timestampTb4b4b4)Tb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3last_timestamp Tff7b72= Te6edf3sender_timestampTb4b4b4;

Tffa657uint32_t Te6edf3now Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeUniqueTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3last_activity Tff7b72= Te6edf3nowTb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3push_failures Tff7b72= T79c0ff0Tb4b4b4; T8b949e// reset so push can resume (if prev failed)

T8b949e// len can be > original length, but 'text' will be padded with zeroes
Te6edf3dataTb4b4b4[Te6edf3lenTb4b4b4] Tff7b72= T79c0ff0Tb4b4b4; T8b949e// need to make a C string again, with null terminator

Tffa657uint32_t Te6edf3ack_hashTb4b4b4; T8b949e// calc truncated hash of the message timestamp + text + sender pub_key, to prove to
T8b949e// sender that we got it
Te6edf3meshTff7b72:Tff7b72:Te6edf3UtilsTff7b72:Tff7b72:Te6edf3sha256Tb4b4b4(Tb4b4b4(Tffa657uint8_t Tff7b72*Tb4b4b4)Tff7b72&Te6edf3ack_hashTb4b4b4, T79c0ff4Tb4b4b4, Te6edf3dataTb4b4b4, T79c0ff5 Tff7b72+ Te6edf3strlenTb4b4b4(Tb4b4b4(Tffa657char Tff7b72*Tb4b4b4)Tff7b72&Te6edf3dataTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3idTb4b4b4.Te6edf3pub_keyTb4b4b4,
Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;

Tffa657uint8_t Te6edf3tempTb4b4b4[T79c0ff166Tb4b4b4]Tb4b4b4;
Tffa657bool Te6edf3send_ackTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3flags Tff7b72=Tff7b72= Te6edf3TXT_TYPE_CLI_DATATb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3isAdminTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3is_retryTb4b4b4) Tb4b4b4{
Te6edf3tempTb4b4b4[T79c0ff5Tb4b4b4] Tff7b72= T79c0ff0Tb4b4b4; T8b949e// no reply
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3handleCommandTb4b4b4(Te6edf3sender_timestampTb4b4b4, Tb4b4b4(Tffa657char Tff7b72*Tb4b4b4)Tff7b72&Te6edf3dataTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4, Tb4b4b4(Tffa657char Tff7b72*Tb4b4b4)Tff7b72&Te6edf3tempTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4)Tb4b4b4;
Te6edf3tempTb4b4b4[T79c0ff4Tb4b4b4] Tff7b72= Tb4b4b4(Te6edf3TXT_TYPE_CLI_DATA Tff7b72<Tff7b72< T79c0ff2Tb4b4b4)Tb4b4b4; T8b949e// attempt and flags, (NOTE: legacy was: TXT_TYPE_PLAIN)
Tb4b4b4}
Te6edf3send_ack Tff7b72= Tffa657falseTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3tempTb4b4b4[T79c0ff5Tb4b4b4] Tff7b72= T79c0ff0Tb4b4b4; T8b949e// no reply
Te6edf3send_ack Tff7b72= Tffa657falseTb4b4b4; T8b949e// and no ACK... user shoudn't be sending these
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{ T8b949e// TXT_TYPE_PLAIN
Tff7b72if Tb4b4b4(Tb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3permissions Tff7b72& Te6edf3PERM_ACL_ROLE_MASKTb4b4b4) Tff7b72=Tff7b72= Te6edf3PERM_ACL_GUESTTb4b4b4) Tb4b4b4{
Te6edf3tempTb4b4b4[T79c0ff5Tb4b4b4] Tff7b72= T79c0ff0Tb4b4b4; T8b949e// no reply
Te6edf3send_ack Tff7b72= Tffa657falseTb4b4b4; T8b949e// no ACK
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3is_retryTb4b4b4) Tb4b4b4{
Te6edf3addPostTb4b4b4(Te6edf3clientTb4b4b4, Tb4b4b4(Tff7b72const Tffa657char Tff7b72*Tb4b4b4)Tff7b72&Te6edf3dataTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3tempTb4b4b4[T79c0ff5Tb4b4b4] Tff7b72= T79c0ff0Tb4b4b4; T8b949e// no reply (ACK is enough)
Te6edf3send_ack Tff7b72= Tffa657trueTb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tffa657uint32_t Te6edf3delay_millisTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3send_ackTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72=Tff7b72= Te6edf3OUT_PATH_UNKNOWNTb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3ack Tff7b72= Te6edf3createAckTb4b4b4(Te6edf3ack_hashTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3ackTb4b4b4) Te6edf3sendFloodReplyTb4b4b4(Te6edf3ackTb4b4b4, Te6edf3TXT_ACK_DELAYTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3delay_millis Tff7b72= Te6edf3TXT_ACK_DELAY Tff7b72+ Te6edf3REPLY_DELAY_MILLISTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tffa657uint32_t Te6edf3d Tff7b72= Te6edf3TXT_ACK_DELAYTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3getExtraAckTransmitCountTb4b4b4(Tb4b4b4) Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3a1 Tff7b72= Te6edf3createMultiAckTb4b4b4(Te6edf3ack_hashTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3a1Tb4b4b4) Te6edf3sendDirectTb4b4b4(Te6edf3a1Tb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_pathTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_lenTb4b4b4, Te6edf3dTb4b4b4)Tb4b4b4;
Te6edf3d Tff7b72+Tff7b72= T79c0ff300Tb4b4b4;
Tb4b4b4}

Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3a2 Tff7b72= Te6edf3createAckTb4b4b4(Te6edf3ack_hashTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3a2Tb4b4b4) Te6edf3sendDirectTb4b4b4(Te6edf3a2Tb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_pathTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_lenTb4b4b4, Te6edf3dTb4b4b4)Tb4b4b4;
Te6edf3delay_millis Tff7b72= Te6edf3d Tff7b72+ Te6edf3REPLY_DELAY_MILLISTb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3delay_millis Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}

Tffa657int Te6edf3text_len Tff7b72= Te6edf3strlenTb4b4b4(Tb4b4b4(Tffa657char Tff7b72*Tb4b4b4)Tff7b72&Te6edf3tempTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3text_len Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3now Tff7b72=Tff7b72= Te6edf3sender_timestampTb4b4b4) Tb4b4b4{
T8b949e// WORKAROUND: the two timestamps need to be different, in the CLI view
Te6edf3nowTff7b72+Tff7b72+Tb4b4b4;
Tb4b4b4}
Te6edf3memcpyTb4b4b4(Te6edf3tempTb4b4b4, Tff7b72&Te6edf3nowTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// mostly an extra blob to help make packet_hash unique

T8b949e// calc expected ACK reply
T8b949e// mesh::Utils::sha256((uint8_t *)&expected_ack_crc, 4, temp, 5 + text_len, self_id.pub_key,
T8b949e// PUB_KEY_SIZE);

Tff7b72auto Te6edf3reply Tff7b72= Te6edf3createDatagramTb4b4b4(Te6edf3PAYLOAD_TYPE_TXT_MSGTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3idTb4b4b4, Te6edf3secretTb4b4b4, Te6edf3tempTb4b4b4, T79c0ff5 Tff7b72+ Te6edf3text_lenTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3replyTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72=Tff7b72= Te6edf3OUT_PATH_UNKNOWNTb4b4b4) Tb4b4b4{
Te6edf3sendFloodReplyTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3delay_millis Tff7b72+ Te6edf3SERVER_RESPONSE_DELAYTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3sendDirectTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_pathTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_lenTb4b4b4, Te6edf3delay_millis Tff7b72+ Te6edf3SERVER_RESPONSE_DELAYTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffonPeerDataRecv: possible replay attack detectedTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3type Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_REQ Tff7b72&Tff7b72& Te6edf3len Tff7b72>Tff7b72= T79c0ff5Tb4b4b4) Tb4b4b4{
Tffa657uint32_t Te6edf3sender_timestampTb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3sender_timestampTb4b4b4, Te6edf3dataTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// timestamp (by sender's RTC clock - which could be wrong)
Tff7b72if Tb4b4b4(Te6edf3sender_timestamp Tff7b72< Te6edf3clientTff7b72-Tff7b72>Te6edf3last_timestampTb4b4b4) Tb4b4b4{ T8b949e// prevent replay attacks
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffonPeerDataRecv: possible replay attack detectedTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3clientTff7b72-Tff7b72>Te6edf3last_timestamp Tff7b72= Te6edf3sender_timestampTb4b4b4;

Tffa657uint32_t Te6edf3now Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3last_activity Tff7b72= Te6edf3nowTb4b4b4; T8b949e// <-- THIS will keep client connection alive
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3push_failures Tff7b72= T79c0ff0Tb4b4b4; T8b949e// reset so push can resume (if prev failed)

Tff7b72if Tb4b4b4(Te6edf3dataTb4b4b4[T79c0ff4Tb4b4b4] Tff7b72=Tff7b72= Te6edf3REQ_TYPE_KEEP_ALIVE Tff7b72&Tff7b72& Te6edf3packetTff7b72-Tff7b72>Te6edf3isRouteDirectTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// request type
Tffa657uint32_t Te6edf3forceSince Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3len Tff7b72>Tff7b72= T79c0ff9Tb4b4b4) Tb4b4b4{ T8b949e// optional - last post_timestamp client received
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3forceSinceTb4b4b4, Tff7b72&Te6edf3dataTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// NOTE: this may be 0, if part of decrypted PADDING!
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3dataTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4, Tff7b72&Te6edf3forceSinceTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; T8b949e// make sure there are zeroes in payload (for ack_hash calc below)
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3forceSince Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3sync_since Tff7b72= Te6edf3forceSinceTb4b4b4; T8b949e// force-update the 'sync since'
Tb4b4b4}

Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3pending_ack Tff7b72= T79c0ff0Tb4b4b4;

T8b949e// TODO: Throttle KEEP_ALIVE requests!
T8b949e// if client sends too quickly, evict()

T8b949e// RULE: only send keep_alive response DIRECT!
Tff7b72if Tb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72!Tff7b72= Te6edf3OUT_PATH_UNKNOWNTb4b4b4) Tb4b4b4{
Tffa657uint32_t Te6edf3ack_hashTb4b4b4; T8b949e// calc ACK to prove to sender that we got request
Te6edf3meshTff7b72:Tff7b72:Te6edf3UtilsTff7b72:Tff7b72:Te6edf3sha256Tb4b4b4(Tb4b4b4(Tffa657uint8_t Tff7b72*Tb4b4b4)Tff7b72&Te6edf3ack_hashTb4b4b4, T79c0ff4Tb4b4b4, Te6edf3dataTb4b4b4, T79c0ff9Tb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3idTb4b4b4.Te6edf3pub_keyTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;

Tff7b72auto Te6edf3reply Tff7b72= Te6edf3createAckTb4b4b4(Te6edf3ack_hashTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3replyTb4b4b4) Tb4b4b4{
Te6edf3replyTff7b72-Tff7b72>Te6edf3payloadTb4b4b4[Te6edf3replyTff7b72-Tff7b72>Te6edf3payload_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3getUnsyncedCountTb4b4b4(Te6edf3clientTb4b4b4)Tb4b4b4; T8b949e// NEW: add unsynced counter to end of ACK packet
Te6edf3sendDirectTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_pathTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_lenTb4b4b4, Te6edf3SERVER_RESPONSE_DELAYTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Tffa657int Te6edf3reply_len Tff7b72= Te6edf3handleRequestTb4b4b4(Te6edf3clientTb4b4b4, Te6edf3sender_timestampTb4b4b4, Tff7b72&Te6edf3dataTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4, Te6edf3len Tff7b72- T79c0ff4Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3reply_len Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// valid command
Tff7b72if Tb4b4b4(Te6edf3packetTff7b72-Tff7b72>Te6edf3isRouteFloodTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3path Tff7b72= Te6edf3createPathReturnTb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3idTb4b4b4, Te6edf3secretTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3pathTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3path_lenTb4b4b4,
Te6edf3PAYLOAD_TYPE_RESPONSETb4b4b4, Te6edf3reply_dataTb4b4b4, Te6edf3reply_lenTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pathTb4b4b4) Te6edf3sendFloodReplyTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3SERVER_RESPONSE_DELAYTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3reply Tff7b72= Te6edf3createDatagramTb4b4b4(Te6edf3PAYLOAD_TYPE_RESPONSETb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3idTb4b4b4, Te6edf3secretTb4b4b4, Te6edf3reply_dataTb4b4b4, Te6edf3reply_lenTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3replyTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72!Tff7b72= Te6edf3OUT_PATH_UNKNOWNTb4b4b4) Tb4b4b4{ T8b949e// we have an out_path, so send DIRECT
Te6edf3sendDirectTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_pathTb4b4b4, Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_lenTb4b4b4, Te6edf3SERVER_RESPONSE_DELAYTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3sendFloodReplyTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3SERVER_RESPONSE_DELAYTb4b4b4, Te6edf3packetTff7b72-Tff7b72>Te6edf3getPathHashSizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tffa657bool Td2a8ffMyMesh::onPeerPathRecvTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3packetTb4b4b4, Tffa657int Te6edf3sender_idxTb4b4b4, Tff7b72const Tffa657uint8_t Tff7b72*Te6edf3secretTb4b4b4, Tffa657uint8_t Tff7b72*Te6edf3pathTb4b4b4,
Tffa657uint8_t Te6edf3path_lenTb4b4b4, Tffa657uint8_t Te6edf3extra_typeTb4b4b4, Tffa657uint8_t Tff7b72*Te6edf3extraTb4b4b4, Tffa657uint8_t Te6edf3extra_lenTb4b4b4) Tb4b4b4{
T8b949e// TODO: prevent replay attacks
Tffa657int Te6edf3i Tff7b72= Te6edf3matching_peer_indexesTb4b4b4[Te6edf3sender_idxTb4b4b4]Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3i Tff7b72>Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3i Tff7b72< Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// get from our known_clients table (sender SHOULD already be known in this context)
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffPATH to client, path_len=%dTa5d6ff"Tb4b4b4, Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3path_lenTb4b4b4)Tb4b4b4;
Tff7b72auto Te6edf3client Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tb4b4b4;
Te6edf3clientTff7b72-Tff7b72>Te6edf3out_path_len Tff7b72= Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72:Tff7b72:Te6edf3copyPathTb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3out_pathTb4b4b4, Te6edf3pathTb4b4b4, Te6edf3path_lenTb4b4b4)Tb4b4b4; T8b949e// store a copy of path, for sendDirect()
Te6edf3clientTff7b72-Tff7b72>Te6edf3last_activity Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffonPeerPathRecv: invalid peer idx: %dTa5d6ff"Tb4b4b4, Te6edf3iTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3extra_type Tff7b72=Tff7b72= Te6edf3PAYLOAD_TYPE_ACK Tff7b72&Tff7b72& Te6edf3extra_len Tff7b72>Tff7b72= T79c0ff4Tb4b4b4) Tb4b4b4{
T8b949e// also got an encoded ACK!
Te6edf3processAckTb4b4b4(Te6edf3extraTb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// NOTE: no reciprocal path send!!
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}

Tffa657void Td2a8ffMyMesh::onAckRecvTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3packetTb4b4b4, Tffa657uint32_t Te6edf3ack_crcTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3processAckTb4b4b4(Tb4b4b4(Tffa657uint8_t Tff7b72*Tb4b4b4)Tff7b72&Te6edf3ack_crcTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3packetTff7b72-Tff7b72>Te6edf3markDoNotRetransmitTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// ACK was for this node, so don't retransmit
Tb4b4b4}
Tb4b4b4}

Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3MyMeshTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3MainBoard Tff7b72&Te6edf3boardTb4b4b4, Te6edf3meshTff7b72:Tff7b72:Te6edf3Radio Tff7b72&Te6edf3radioTb4b4b4, Te6edf3meshTff7b72:Tff7b72:Te6edf3MillisecondClock Tff7b72&Te6edf3msTb4b4b4, Te6edf3meshTff7b72:Tff7b72:Te6edf3RNG Tff7b72&Te6edf3rngTb4b4b4,
Te6edf3meshTff7b72:Tff7b72:Te6edf3RTCClock Tff7b72&Te6edf3rtcTb4b4b4, Te6edf3meshTff7b72:Tff7b72:Te6edf3MeshTables Tff7b72&Te6edf3tablesTb4b4b4)
Tff7b72: Te6edf3meshTff7b72:Tff7b72:Te6edf3MeshTb4b4b4(Te6edf3radioTb4b4b4, Te6edf3msTb4b4b4, Te6edf3rngTb4b4b4, Te6edf3rtcTb4b4b4, Tff7b72*Tff7b72new Te6edf3StaticPoolPacketManagerTb4b4b4(T79c0ff32Tb4b4b4)Tb4b4b4, Te6edf3tablesTb4b4b4)Tb4b4b4,
Te6edf3region_mapTb4b4b4(Te6edf3key_storeTb4b4b4)Tb4b4b4, Te6edf3temp_mapTb4b4b4(Te6edf3key_storeTb4b4b4)Tb4b4b4,
Te6edf3_cliTb4b4b4(Te6edf3boardTb4b4b4, Te6edf3rtcTb4b4b4, Te6edf3sensorsTb4b4b4, Te6edf3region_mapTb4b4b4, Te6edf3aclTb4b4b4, Tff7b72&Te6edf3_prefsTb4b4b4, Tff7b72thisTb4b4b4)Tb4b4b4,
Te6edf3telemetryTb4b4b4(Te6edf3MAX_PACKET_PAYLOAD Tff7b72- T79c0ff4Tb4b4b4)
Tb4b4b4{
Te6edf3last_millis Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3uptime_millis Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3next_local_advert Tff7b72= Te6edf3next_flood_advert Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3dirty_contacts_expiry Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3_logging Tff7b72= Tffa657falseTb4b4b4;
Te6edf3region_load_active Tff7b72= Tffa657falseTb4b4b4;
Te6edf3set_radio_at Tff7b72= Te6edf3revert_radio_at Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3recv_pkt_region Tff7b72= Tffa657NULLTb4b4b4;

T8b949e// defaults
Te6edf3_prefsTb4b4b4.Te6edf3airtime_factor Tff7b72= T79c0ff1.0Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3rx_delay_base Tff7b72= T79c0ff0.0fTb4b4b4; T8b949e// off by default, was 10.0
Te6edf3_prefsTb4b4b4.Te6edf3tx_delay_factor Tff7b72= T79c0ff0.5fTb4b4b4; T8b949e// was 0.25f;
Te6edf3_prefsTb4b4b4.Te6edf3direct_tx_delay_factor Tff7b72= T79c0ff0.2fTb4b4b4; T8b949e// was zero
Te6edf3StrHelperTff7b72:Tff7b72:Te6edf3strncpyTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3node_nameTb4b4b4, Te6edf3ADVERT_NAMETb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3node_nameTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3node_lat Tff7b72= Te6edf3ADVERT_LATTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3node_lon Tff7b72= Te6edf3ADVERT_LONTb4b4b4;
Te6edf3StrHelperTff7b72:Tff7b72:Te6edf3strncpyTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3passwordTb4b4b4, Te6edf3ADMIN_PASSWORDTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3passwordTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3freq Tff7b72= Te6edf3LORA_FREQTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3sf Tff7b72= Te6edf3LORA_SFTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3bw Tff7b72= Te6edf3LORA_BWTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3cr Tff7b72= Te6edf3LORA_CRTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3tx_power_dbm Tff7b72= Te6edf3LORA_TX_POWERTb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3disable_fwd Tff7b72= T79c0ff1Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3advert_interval Tff7b72= T79c0ff1Tb4b4b4; T8b949e// default to 2 minutes for NEW installs
Te6edf3_prefsTb4b4b4.Te6edf3flood_advert_interval Tff7b72= T79c0ff47Tb4b4b4; T8b949e// 47 hours
Te6edf3_prefsTb4b4b4.Te6edf3flood_max Tff7b72= T79c0ff64Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3flood_max_unscoped Tff7b72= T79c0ff64Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3flood_max_advert Tff7b72= T79c0ff8Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3interference_threshold Tff7b72= T79c0ff0Tb4b4b4; T8b949e// disabled
Te6edf3_prefsTb4b4b4.Te6edf3cad_enabled Tff7b72= T79c0ff0Tb4b4b4; T8b949e// hardware CAD before TX (off by default; 'set cad on')
Tff7b72#Tff7b72ifdef ROOM_PASSWORD
Te6edf3StrHelperTff7b72:Tff7b72:Te6edf3strncpyTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3guest_passwordTb4b4b4, Te6edf3ROOM_PASSWORDTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3guest_passwordTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif

T8b949e// GPS defaults
Te6edf3_prefsTb4b4b4.Te6edf3gps_enabled Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3gps_interval Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3advert_loc_policy Tff7b72= Te6edf3ADVERT_LOC_PREFSTb4b4b4;

Tff7b72#Tff7b72if defined(USE_SX1262) || defined(USE_SX1268)
Tff7b72#Tff7b72ifdef SX126X_RX_BOOSTED_GAIN
Te6edf3_prefsTb4b4b4.Te6edf3rx_boosted_gain Tff7b72= Te6edf3SX126X_RX_BOOSTED_GAINTb4b4b4;
Tff7b72#Tff7b72else
Te6edf3_prefsTb4b4b4.Te6edf3rx_boosted_gain Tff7b72= T79c0ff1Tb4b4b4; T8b949e// enabled by default;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
Te6edf3_prefsTb4b4b4.Te6edf3radio_fem_rxgain Tff7b72= T79c0ff1Tb4b4b4;
Te6edf3_prefsTb4b4b4.Te6edf3radio_fem_txgain Tff7b72= T79c0ff0Tb4b4b4;

Te6edf3next_post_idx Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3next_client_idx Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3next_push Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3memsetTb4b4b4(Te6edf3postsTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3postsTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3_num_posted Tff7b72= Te6edf3_num_post_pushes Tff7b72= T79c0ff0Tb4b4b4;

Te6edf3memsetTb4b4b4(Te6edf3default_scopeTb4b4b4.Te6edf3keyTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3default_scopeTb4b4b4.Te6edf3keyTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3beginTb4b4b4(Te6edf3FILESYSTEM Tff7b72*Te6edf3fsTb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3MeshTff7b72:Tff7b72:Te6edf3beginTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3_fs Tff7b72= Te6edf3fsTb4b4b4;
T8b949e// load persisted prefs
Te6edf3_cliTb4b4b4.Te6edf3loadPrefsTb4b4b4(Te6edf3_fsTb4b4b4)Tb4b4b4;

Te6edf3aclTb4b4b4.Te6edf3loadTb4b4b4(Te6edf3_fsTb4b4b4, Te6edf3self_idTb4b4b4)Tb4b4b4;
Te6edf3region_mapTb4b4b4.Te6edf3loadTb4b4b4(Te6edf3_fsTb4b4b4)Tb4b4b4;

T8b949e// establish default-scope
Tb4b4b4{
Te6edf3RegionEntryTff7b72* Te6edf3r Tff7b72= Te6edf3region_mapTb4b4b4.Te6edf3getDefaultRegionTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3rTb4b4b4) Tb4b4b4{
Te6edf3region_mapTb4b4b4.Te6edf3getTransportKeysForTb4b4b4(Tff7b72*Te6edf3rTb4b4b4, Tff7b72&Te6edf3default_scopeTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72#Tff7b72ifdef DEFAULT_FLOOD_SCOPE_NAME
Te6edf3r Tff7b72= Te6edf3region_mapTb4b4b4.Te6edf3findByNameTb4b4b4(Te6edf3DEFAULT_FLOOD_SCOPE_NAMETb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3r Tff7b72=Tff7b72= Tffa657NULLTb4b4b4) Tb4b4b4{
Te6edf3r Tff7b72= Te6edf3region_mapTb4b4b4.Te6edf3putRegionTb4b4b4(Te6edf3DEFAULT_FLOOD_SCOPE_NAMETb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4; T8b949e// auto-create the default scope region
Tff7b72if Tb4b4b4(Te6edf3rTb4b4b4) Tb4b4b4{ Te6edf3rTff7b72-Tff7b72>Te6edf3flags Tff7b72= T79c0ff0Tb4b4b4; Tb4b4b4} T8b949e// Allow-flood
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3rTb4b4b4) Tb4b4b4{
Te6edf3region_mapTb4b4b4.Te6edf3setDefaultRegionTb4b4b4(Te6edf3rTb4b4b4)Tb4b4b4;
Te6edf3region_mapTb4b4b4.Te6edf3getTransportKeysForTb4b4b4(Tff7b72*Te6edf3rTb4b4b4, Tff7b72&Te6edf3default_scopeTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4}

Te6edf3radio_driverTb4b4b4.Te6edf3setParamsTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3freqTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3bwTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3sfTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3crTb4b4b4)Tb4b4b4;
Te6edf3radio_driverTb4b4b4.Te6edf3setTxPowerTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3tx_power_dbmTb4b4b4)Tb4b4b4;
Te6edf3radio_driverTb4b4b4.Te6edf3setRxBoostedGainModeTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3rx_boosted_gainTb4b4b4)Tb4b4b4;
Te6edf3boardTb4b4b4.Te6edf3setLoRaFemLnaEnabledTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3radio_fem_rxgainTb4b4b4)Tb4b4b4;
Te6edf3boardTb4b4b4.Te6edf3setLoRaFemPaGainEnabledTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3radio_fem_txgainTb4b4b4)Tb4b4b4;

Te6edf3updateAdvertTimerTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3updateFloodAdvertTimerTb4b4b4(Tb4b4b4)Tb4b4b4;

Te6edf3boardTb4b4b4.Te6edf3setAdcMultiplierTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3adc_multiplierTb4b4b4)Tb4b4b4;

Tff7b72#Tff7b72if ENV_INCLUDE_GPS == 1
Te6edf3applyGpsPrefsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3sendFloodScopedTb4b4b4(Tff7b72const Te6edf3TransportKeyTff7b72& Te6edf3scopeTb4b4b4, Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3pktTb4b4b4, Tffa657uint32_t Te6edf3delay_millisTb4b4b4, Tffa657uint8_t Te6edf3path_hash_sizeTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3scopeTb4b4b4.Te6edf3isNullTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3sendFloodTb4b4b4(Te6edf3pktTb4b4b4, Te6edf3delay_millisTb4b4b4, Te6edf3path_hash_sizeTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tffa657uint16_t Te6edf3codesTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4;
Te6edf3codesTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72= Te6edf3scopeTb4b4b4.Te6edf3calcTransportCodeTb4b4b4(Te6edf3pktTb4b4b4)Tb4b4b4;
Te6edf3codesTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72= T79c0ff0Tb4b4b4; T8b949e// REVISIT: set to 'home' Region, for sender/return region?
Te6edf3sendFloodTb4b4b4(Te6edf3pktTb4b4b4, Te6edf3codesTb4b4b4, Te6edf3delay_millisTb4b4b4, Te6edf3path_hash_sizeTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3sendFloodReplyTb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657unsigned Tffa657long Te6edf3delay_millisTb4b4b4, Tffa657uint8_t Te6edf3path_hash_sizeTb4b4b4) Tb4b4b4{
Te6edf3TransportKey Te6edf3req_scopeTb4b4b4;
Tffa657bool Te6edf3is_wildcard Tff7b72= Te6edf3recv_pkt_region Tff7b72!Tff7b72= Tffa657NULL Tff7b72&Tff7b72& Te6edf3recv_pkt_regionTff7b72-Tff7b72>Te6edf3isWildcardTb4b4b4(Tb4b4b4)Tb4b4b4;
Tffa657bool Te6edf3req_scope_known Tff7b72= Te6edf3recv_pkt_region Tff7b72!Tff7b72= Tffa657NULL Tff7b72&Tff7b72& Tff7b72!Te6edf3is_wildcard
Tff7b72&Tff7b72& Te6edf3region_mapTb4b4b4.Te6edf3getTransportKeysForTb4b4b4(Tff7b72*Te6edf3recv_pkt_regionTb4b4b4, Tff7b72&Te6edf3req_scopeTb4b4b4, T79c0ff1Tb4b4b4) Tff7b72> T79c0ff0Tb4b4b4;

Tff7b72switch Tb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3chooseReplyScopeTb4b4b4(Te6edf3req_scope_knownTb4b4b4, Te6edf3is_wildcardTb4b4b4, Tff7b72!Te6edf3default_scopeTb4b4b4.Te6edf3isNullTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72case Tff7b72meshTff7b72:Tff7b72:Tff7b72REPLY_SCOPE_REQUESTTb4b4b4:
Te6edf3sendFloodScopedTb4b4b4(Te6edf3req_scopeTb4b4b4, Te6edf3packetTb4b4b4, Te6edf3delay_millisTb4b4b4, Te6edf3path_hash_sizeTb4b4b4)Tb4b4b4; T8b949e// reply with same scope as request
Tff7b72breakTb4b4b4;
Tff7b72case Tff7b72meshTff7b72:Tff7b72:Tff7b72REPLY_SCOPE_DEFAULTTb4b4b4:
T8b949e// requester's scope is unknown: DIRECT request (no transport codes), or code matched no Region.
T8b949e// un-scoped would be dropped at hop 0 by repeaters running flood.max.unscoped=0
Te6edf3sendFloodScopedTb4b4b4(Te6edf3default_scopeTb4b4b4, Te6edf3packetTb4b4b4, Te6edf3delay_millisTb4b4b4, Te6edf3path_hash_sizeTb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tff7b72case Tff7b72meshTff7b72:Tff7b72:Tff7b72REPLY_SCOPE_NONETb4b4b4:
Te6edf3sendFloodTb4b4b4(Te6edf3packetTb4b4b4, Te6edf3delay_millisTb4b4b4, Te6edf3path_hash_sizeTb4b4b4)Tb4b4b4; T8b949e// send un-scoped
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3applyTempRadioParamsTb4b4b4(Tffa657float Te6edf3freqTb4b4b4, Tffa657float Te6edf3bwTb4b4b4, Tffa657uint8_t Te6edf3sfTb4b4b4, Tffa657uint8_t Te6edf3crTb4b4b4, Tffa657int Te6edf3timeout_minsTb4b4b4) Tb4b4b4{
Te6edf3set_radio_at Tff7b72= Te6edf3futureMillisTb4b4b4(T79c0ff2000Tb4b4b4)Tb4b4b4; T8b949e// give CLI reply some time to be sent back, before applying temp radio params
Te6edf3pending_freq Tff7b72= Te6edf3freqTb4b4b4;
Te6edf3pending_bw Tff7b72= Te6edf3bwTb4b4b4;
Te6edf3pending_sf Tff7b72= Te6edf3sfTb4b4b4;
Te6edf3pending_cr Tff7b72= Te6edf3crTb4b4b4;

Te6edf3revert_radio_at Tff7b72= Te6edf3futureMillisTb4b4b4(T79c0ff2000 Tff7b72+ Te6edf3timeout_mins Tff7b72* T79c0ff60 Tff7b72* T79c0ff1000Tb4b4b4)Tb4b4b4; T8b949e// schedule when to revert radio params
Tb4b4b4}

Tffa657bool Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3formatFileSystemTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if defined(NRF52_PLATFORM)
Tff7b72return Te6edf3InternalFSTb4b4b4.Te6edf3formatTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif defined(RP2040_PLATFORM)
Tff7b72return Te6edf3LittleFSTb4b4b4.Te6edf3formatTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif defined(ESP32)
Tff7b72return Te6edf3SPIFFSTb4b4b4.Te6edf3formatTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72#Tff7b72error "need to implement file system erase"
Tff7b72return Tffa657falseTb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3sendSelfAdvertisementTb4b4b4(Tffa657int Te6edf3delay_millisTb4b4b4, Tffa657bool Te6edf3floodTb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3pkt Tff7b72= Te6edf3createSelfAdvertTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pktTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3floodTb4b4b4) Tb4b4b4{
Te6edf3sendFloodScopedTb4b4b4(Te6edf3default_scopeTb4b4b4, Te6edf3pktTb4b4b4, Te6edf3delay_millisTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3path_hash_mode Tff7b72+ T79c0ff1Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3sendZeroHopTb4b4b4(Te6edf3pktTb4b4b4, Te6edf3delay_millisTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffERROR: unable to create advertisement packet!Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3updateAdvertTimerTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3advert_interval Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// schedule local advert timer
Te6edf3next_local_advert Tff7b72= Te6edf3futureMillisTb4b4b4(Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3_prefsTb4b4b4.Te6edf3advert_interval Tff7b72* T79c0ff2 Tff7b72* T79c0ff60 Tff7b72* T79c0ff1000Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3next_local_advert Tff7b72= T79c0ff0Tb4b4b4; T8b949e// stop the timer
Tb4b4b4}
Tb4b4b4}
Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3updateFloodAdvertTimerTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3flood_advert_interval Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// schedule flood advert timer
Te6edf3next_flood_advert Tff7b72= Te6edf3futureMillisTb4b4b4(Tb4b4b4(Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3_prefsTb4b4b4.Te6edf3flood_advert_intervalTb4b4b4) Tff7b72* T79c0ff60 Tff7b72* T79c0ff60 Tff7b72* T79c0ff1000Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3next_flood_advert Tff7b72= T79c0ff0Tb4b4b4; T8b949e// stop the timer
Tb4b4b4}
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3dumpLogFileTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if defined(RP2040_PLATFORM)
Te6edf3File Te6edf3f Tff7b72= Te6edf3_fsTff7b72-Tff7b72>Te6edf3openTb4b4b4(Te6edf3PACKET_LOG_FILETb4b4b4, Ta5d6ff"Ta5d6ffrTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3File Te6edf3f Tff7b72= Te6edf3_fsTff7b72-Tff7b72>Te6edf3openTb4b4b4(Te6edf3PACKET_LOG_FILETb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4) Tb4b4b4{
Tff7b72while Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3availableTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tffa657int Te6edf3c Tff7b72= Te6edf3fTb4b4b4.Te6edf3readTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3c Tff7b72< T79c0ff0Tb4b4b4) Tff7b72breakTb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Tb4b4b4(Tffa657charTb4b4b4)Te6edf3cTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3fTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3setTxPowerTb4b4b4(Tffa657int8_t Te6edf3power_dbmTb4b4b4) Tb4b4b4{
Te6edf3radio_driverTb4b4b4.Te6edf3setTxPowerTb4b4b4(Te6edf3power_dbmTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657bool Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3setRxBoostedGainTb4b4b4(Tffa657bool Te6edf3enableTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3radio_driverTb4b4b4.Te6edf3setRxBoostedGainModeTb4b4b4(Te6edf3enableTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3saveIdentityTb4b4b4(Tff7b72const Te6edf3meshTff7b72:Tff7b72:Te6edf3LocalIdentity Tff7b72&Te6edf3new_idTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
Te6edf3IdentityStore Te6edf3storeTb4b4b4(Tff7b72*Te6edf3_fsTb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif defined(ESP32)
Te6edf3IdentityStore Te6edf3storeTb4b4b4(Tff7b72*Te6edf3_fsTb4b4b4, Ta5d6ff"Ta5d6ff/identityTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif defined(RP2040_PLATFORM)
Te6edf3IdentityStore Te6edf3storeTb4b4b4(Tff7b72*Te6edf3_fsTb4b4b4, Ta5d6ff"Ta5d6ff/identityTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72#Tff7b72error "need to define saveIdentity()"
Tff7b72#Tff7b72endif
Te6edf3storeTb4b4b4.Te6edf3saveTb4b4b4(Ta5d6ff"Ta5d6ff_mainTa5d6ff"Tb4b4b4, Te6edf3new_idTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3startRegionsLoadTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3temp_mapTb4b4b4.Te6edf3resetFromTb4b4b4(Te6edf3region_mapTb4b4b4)Tb4b4b4; T8b949e// rebuild regions in a temp instance
Te6edf3memsetTb4b4b4(Te6edf3load_stackTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3load_stackTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3load_stackTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72= Tff7b72&Te6edf3temp_mapTb4b4b4.Te6edf3getWildcardTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3region_load_active Tff7b72= Tffa657trueTb4b4b4;
Tb4b4b4}

Tffa657bool Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3saveRegionsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3region_mapTb4b4b4.Te6edf3saveTb4b4b4(Te6edf3_fsTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3onDefaultRegionChangedTb4b4b4(Tff7b72const Te6edf3RegionEntryTff7b72* Te6edf3rTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3rTb4b4b4) Tb4b4b4{
Te6edf3region_mapTb4b4b4.Te6edf3getTransportKeysForTb4b4b4(Tff7b72*Te6edf3rTb4b4b4, Tff7b72&Te6edf3default_scopeTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3memsetTb4b4b4(Te6edf3default_scopeTb4b4b4.Te6edf3keyTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3default_scopeTb4b4b4.Te6edf3keyTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3clearStatsTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3radio_driverTb4b4b4.Te6edf3resetStatsTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3resetStatsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4(Tb4b4b4(Te6edf3SimpleMeshTables Tff7b72*Tb4b4b4)Te6edf3getTablesTb4b4b4(Tb4b4b4)Tb4b4b4)Tff7b72-Tff7b72>Te6edf3resetStatsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3formatStatsReplyTb4b4b4(Tffa657char Tff7b72*Te6edf3replyTb4b4b4) Tb4b4b4{
Te6edf3StatsFormatHelperTff7b72:Tff7b72:Te6edf3formatCoreStatsTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3boardTb4b4b4, Tff7b72*Te6edf3_msTb4b4b4, Te6edf3_err_flagsTb4b4b4, Te6edf3_mgrTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3formatRadioStatsReplyTb4b4b4(Tffa657char Tff7b72*Te6edf3replyTb4b4b4) Tb4b4b4{
Te6edf3StatsFormatHelperTff7b72:Tff7b72:Te6edf3formatRadioStatsTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3_radioTb4b4b4, Te6edf3radio_driverTb4b4b4, Te6edf3getTotalAirTimeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3getReceiveAirTimeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3formatPacketStatsReplyTb4b4b4(Tffa657char Tff7b72*Te6edf3replyTb4b4b4) Tb4b4b4{
Te6edf3StatsFormatHelperTff7b72:Tff7b72:Te6edf3formatPacketStatsTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3radio_driverTb4b4b4, Te6edf3getNumSentFloodTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3getNumSentDirectTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3getNumRecvFloodTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3getNumRecvDirectTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3handleCommandTb4b4b4(Tffa657uint32_t Te6edf3sender_timestampTb4b4b4, Tffa657char Tff7b72*Te6edf3commandTb4b4b4, Tffa657char Tff7b72*Te6edf3replyTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3region_load_activeTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3StrHelperTff7b72:Tff7b72:Te6edf3isBlankTb4b4b4(Te6edf3commandTb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// empty/blank line, signal to terminate 'load' operation
Te6edf3region_map Tff7b72= Te6edf3temp_mapTb4b4b4; T8b949e// copy over the temp instance as new current map
Te6edf3region_load_active Tff7b72= Tffa657falseTb4b4b4;

Te6edf3sprintfTb4b4b4(Te6edf3replyTb4b4b4, Ta5d6ff"Ta5d6ffOK - loaded %d regionsTa5d6ff"Tb4b4b4, Te6edf3region_mapTb4b4b4.Te6edf3getCountTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tffa657char Tff7b72*Te6edf3np Tff7b72= Te6edf3commandTb4b4b4;
Tff7b72while Tb4b4b4(Tff7b72*Te6edf3np Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ff Ta5d6ff'Tb4b4b4) Te6edf3npTff7b72+Tff7b72+Tb4b4b4; T8b949e// skip indent
Tffa657int Te6edf3indent Tff7b72= Te6edf3np Tff7b72- Te6edf3commandTb4b4b4;

Tffa657char Tff7b72*Te6edf3ep Tff7b72= Te6edf3npTb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3RegionMapTff7b72:Tff7b72:Te6edf3is_name_charTb4b4b4(Tff7b72*Te6edf3epTb4b4b4)Tb4b4b4) Te6edf3epTff7b72+Tff7b72+Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72*Te6edf3epTb4b4b4) Tb4b4b4{ Tff7b72*Te6edf3epTff7b72+Tff7b72+ Tff7b72= T79c0ff0Tb4b4b4; Tb4b4b4} T8b949e// set null terminator for end of name

Tff7b72while Tb4b4b4(Tff7b72*Te6edf3ep Tff7b72&Tff7b72& Tff7b72*Te6edf3ep Tff7b72!Tff7b72= Ta5d6ff'Ta5d6ffFTa5d6ff'Tb4b4b4) Te6edf3epTff7b72+Tff7b72+Tb4b4b4; T8b949e// look for (optional) flags

Tff7b72if Tb4b4b4(Te6edf3indent Tff7b72> T79c0ff0 Tff7b72&Tff7b72& Te6edf3indent Tff7b72< T79c0ff8 Tff7b72&Tff7b72& Te6edf3strlenTb4b4b4(Te6edf3npTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3parent Tff7b72= Te6edf3load_stackTb4b4b4[Te6edf3indent Tff7b72- T79c0ff1Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3parentTb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3old Tff7b72= Te6edf3region_mapTb4b4b4.Te6edf3findByNameTb4b4b4(Te6edf3npTb4b4b4)Tb4b4b4;
Tff7b72auto Te6edf3nw Tff7b72= Te6edf3temp_mapTb4b4b4.Te6edf3putRegionTb4b4b4(Te6edf3npTb4b4b4, Te6edf3parentTff7b72-Tff7b72>Te6edf3idTb4b4b4, Te6edf3old Tff7b72? Te6edf3oldTff7b72-Tff7b72>Te6edf3id Tff7b72: T79c0ff0Tb4b4b4)Tb4b4b4; T8b949e// carry-over the current ID (if name already exists)
Tff7b72if Tb4b4b4(Te6edf3nwTb4b4b4) Tb4b4b4{
Te6edf3nwTff7b72-Tff7b72>Te6edf3flags Tff7b72= Te6edf3old Tff7b72? Te6edf3oldTff7b72-Tff7b72>Te6edf3flags Tff7b72: Tb4b4b4(Tff7b72*Te6edf3ep Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ffFTa5d6ff' Tff7b72? T79c0ff0 Tff7b72: Te6edf3REGION_DENY_FLOODTb4b4b4)Tb4b4b4; T8b949e// carry-over flags from curr

Te6edf3load_stackTb4b4b4[Te6edf3indentTb4b4b4] Tff7b72= Te6edf3nwTb4b4b4; T8b949e// keep pointers to parent regions, to resolve parent_id's
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Te6edf3replyTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}
Tff7b72returnTb4b4b4;
Tb4b4b4}

Tff7b72while Tb4b4b4(Tff7b72*Te6edf3command Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ff Ta5d6ff'Tb4b4b4)
Te6edf3commandTff7b72+Tff7b72+Tb4b4b4; T8b949e// skip leading spaces

Tff7b72if Tb4b4b4(Te6edf3strlenTb4b4b4(Te6edf3commandTb4b4b4) Tff7b72> T79c0ff4 Tff7b72&Tff7b72& Te6edf3commandTb4b4b4[T79c0ff2Tb4b4b4] Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ff|Ta5d6ff'Tb4b4b4) Tb4b4b4{ T8b949e// optional prefix (for companion radio CLI)
Te6edf3memcpyTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3commandTb4b4b4, T79c0ff3Tb4b4b4)Tb4b4b4; T8b949e// reflect the prefix back
Te6edf3reply Tff7b72+Tff7b72= T79c0ff3Tb4b4b4;
Te6edf3command Tff7b72+Tff7b72= T79c0ff3Tb4b4b4;
Tb4b4b4}

T8b949e// handle ACL related commands
Tff7b72if Tb4b4b4(Te6edf3memcmpTb4b4b4(Te6edf3commandTb4b4b4, Ta5d6ff"Ta5d6ffsetperm Ta5d6ff"Tb4b4b4, T79c0ff8Tb4b4b4) Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{ T8b949e// format: setperm {pubkey-hex} {permissions-int8}
Tffa657charTff7b72* Te6edf3hex Tff7b72= Tff7b72&Te6edf3commandTb4b4b4[T79c0ff8Tb4b4b4]Tb4b4b4;
Tffa657charTff7b72* Te6edf3sp Tff7b72= Te6edf3strchrTb4b4b4(Te6edf3hexTb4b4b4, Ta5d6ff'Ta5d6ff Ta5d6ff'Tb4b4b4)Tb4b4b4; T8b949e// look for separator char
Tff7b72if Tb4b4b4(Te6edf3sp Tff7b72=Tff7b72= Tffa657NULLTb4b4b4) Tb4b4b4{
Te6edf3strcpyTb4b4b4(Te6edf3replyTb4b4b4, Ta5d6ff"Ta5d6ffErr - bad paramsTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72*Te6edf3spTff7b72+Tff7b72+ Tff7b72= T79c0ff0Tb4b4b4; T8b949e// replace space with null terminator

Tffa657uint8_t Te6edf3pubkeyTb4b4b4[Te6edf3PUB_KEY_SIZETb4b4b4]Tb4b4b4;
Tffa657int Te6edf3hex_len Tff7b72= Te6edf3minTb4b4b4(Te6edf3sp Tff7b72- Te6edf3hexTb4b4b4, Te6edf3PUB_KEY_SIZETff7b72*T79c0ff2Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3meshTff7b72:Tff7b72:Te6edf3UtilsTff7b72:Tff7b72:Te6edf3fromHexTb4b4b4(Te6edf3pubkeyTb4b4b4, Te6edf3hex_len Tff7b72/ T79c0ff2Tb4b4b4, Te6edf3hexTb4b4b4)Tb4b4b4) Tb4b4b4{
Tffa657uint8_t Te6edf3perms Tff7b72= Te6edf3atoiTb4b4b4(Te6edf3spTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3aclTb4b4b4.Te6edf3applyPermissionsTb4b4b4(Te6edf3self_idTb4b4b4, Te6edf3pubkeyTb4b4b4, Te6edf3hex_len Tff7b72/ T79c0ff2Tb4b4b4, Te6edf3permsTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3dirty_contacts_expiry Tff7b72= Te6edf3futureMillisTb4b4b4(Te6edf3LAZY_CONTACTS_WRITE_DELAYTb4b4b4)Tb4b4b4; T8b949e// trigger acl.save()
Te6edf3strcpyTb4b4b4(Te6edf3replyTb4b4b4, Ta5d6ff"Ta5d6ffOKTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3strcpyTb4b4b4(Te6edf3replyTb4b4b4, Ta5d6ff"Ta5d6ffErr - invalid paramsTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3strcpyTb4b4b4(Te6edf3replyTb4b4b4, Ta5d6ff"Ta5d6ffErr - bad pubkeyTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sender_timestamp Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3strcmpTb4b4b4(Te6edf3commandTb4b4b4, Ta5d6ff"Ta5d6ffget aclTa5d6ff"Tb4b4b4) Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Ta5d6ff"Ta5d6ffACL:Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tffa657int Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3c Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cTff7b72-Tff7b72>Te6edf3permissions Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tff7b72continueTb4b4b4; T8b949e// skip deleted (or guest) entries

Te6edf3SerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff%02X Ta5d6ff"Tb4b4b4, Te6edf3cTff7b72-Tff7b72>Te6edf3permissionsTb4b4b4)Tb4b4b4;
Te6edf3meshTff7b72:Tff7b72:Te6edf3UtilsTff7b72:Tff7b72:Te6edf3printHexTb4b4b4(Te6edf3SerialTb4b4b4, Te6edf3cTff7b72-Tff7b72>Te6edf3idTb4b4b4.Te6edf3pub_keyTb4b4b4, Te6edf3PUB_KEY_SIZETb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3replyTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3strncmpTb4b4b4(Te6edf3commandTb4b4b4, Ta5d6ff"Ta5d6ffroom.postTa5d6ff"Tb4b4b4, T79c0ff9Tb4b4b4) Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Tffa657charTff7b72* Te6edf3msg Tff7b72= Te6edf3command Tff7b72+ T79c0ff9Tb4b4b4;
Tff7b72while Tb4b4b4(Tff7b72*Te6edf3msg Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ff Ta5d6ff'Tb4b4b4) Te6edf3msgTff7b72+Tff7b72+Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72*Te6edf3msg Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3snprintfTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3MAX_POST_TEXT_LENTb4b4b4, Ta5d6ff"Ta5d6ffERR empty messageTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3addSystemPostTb4b4b4(Te6edf3msgTb4b4b4)Tb4b4b4;
Te6edf3snprintfTb4b4b4(Te6edf3replyTb4b4b4, Te6edf3MAX_POST_TEXT_LENTb4b4b4, Ta5d6ff"Ta5d6ffOKTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72elseTb4b4b4{
Te6edf3_cliTb4b4b4.Te6edf3handleCommandTb4b4b4(Te6edf3sender_timestampTb4b4b4, Te6edf3commandTb4b4b4, Te6edf3replyTb4b4b4)Tb4b4b4; T8b949e// common CLI commands
Tb4b4b4}
Tb4b4b4}

Tffa657bool Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3saveFilterTb4b4b4(Te6edf3ClientInfoTff7b72* Te6edf3clientTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3clientTff7b72-Tff7b72>Te6edf3isAdminTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// only save Admins
Tb4b4b4}

Tffa657void Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3loopTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3MeshTff7b72:Tff7b72:Te6edf3loopTb4b4b4(Tb4b4b4)Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3millisHasNowPassedTb4b4b4(Te6edf3next_pushTb4b4b4) Tff7b72&Tff7b72& Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4) Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
T8b949e// check for ACK timeouts
Tff7b72for Tb4b4b4(Tffa657int Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3c Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3iTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3pending_ack Tff7b72&Tff7b72& Te6edf3millisHasNowPassedTb4b4b4(Te6edf3cTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3ack_timeoutTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3cTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3push_failuresTff7b72+Tff7b72+Tb4b4b4;
Te6edf3cTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3pending_ack Tff7b72= T79c0ff0Tb4b4b4; T8b949e// reset (TODO: keep prev expected_ack's in a list, incase they arrive LATER, after we retry)
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffpending ACK timed out: push_failures: %dTa5d6ff"Tb4b4b4, Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3cTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3push_failuresTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
T8b949e// check next Round-Robin client, and sync next new post
Tff7b72auto Te6edf3client Tff7b72= Te6edf3aclTb4b4b4.Te6edf3getClientByIdxTb4b4b4(Te6edf3next_client_idxTb4b4b4)Tb4b4b4;
Tffa657bool Te6edf3did_push Tff7b72= Tffa657falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3pending_ack Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3clientTff7b72-Tff7b72>Te6edf3last_activity Tff7b72!Tff7b72= T79c0ff0 Tff7b72&Tff7b72&
Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3push_failures Tff7b72< T79c0ff3Tb4b4b4) Tb4b4b4{ T8b949e// not already waiting for ACK, AND not evicted, AND retries not max
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffloop - checking for client %02XTa5d6ff"Tb4b4b4, Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3clientTff7b72-Tff7b72>Te6edf3idTb4b4b4.Te6edf3pub_keyTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tffa657uint32_t Te6edf3now Tff7b72= Te6edf3getRTCClockTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3getCurrentTimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tffa657int Te6edf3k Tff7b72= T79c0ff0Tb4b4b4, Te6edf3idx Tff7b72= Te6edf3next_post_idxTb4b4b4; Te6edf3k Tff7b72< Te6edf3MAX_UNSYNCED_POSTSTb4b4b4; Te6edf3kTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72auto Te6edf3p Tff7b72= Tff7b72&Te6edf3postsTb4b4b4[Te6edf3idxTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3now Tff7b72>Tff7b72= Te6edf3pTff7b72-Tff7b72>Te6edf3post_timestamp Tff7b72+ Te6edf3POST_SYNC_DELAY_SECS Tff7b72&Tff7b72&
Te6edf3pTff7b72-Tff7b72>Te6edf3post_timestamp Tff7b72> Te6edf3clientTff7b72-Tff7b72>Te6edf3extraTb4b4b4.Te6edf3roomTb4b4b4.Te6edf3sync_since T8b949e// is new post for this Client?
Tff7b72&Tff7b72& Tff7b72!Te6edf3pTff7b72-Tff7b72>Te6edf3authorTb4b4b4.Te6edf3matchesTb4b4b4(Te6edf3clientTff7b72-Tff7b72>Te6edf3idTb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// don't push posts to the author
T8b949e// push this post to Client, then wait for ACK
Te6edf3pushPostToClientTb4b4b4(Te6edf3clientTb4b4b4, Tff7b72*Te6edf3pTb4b4b4)Tb4b4b4;
Te6edf3did_push Tff7b72= Tffa657trueTb4b4b4;
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffloop - pushed to client %02X: %sTa5d6ff"Tb4b4b4, Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3clientTff7b72-Tff7b72>Te6edf3idTb4b4b4.Te6edf3pub_keyTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3pTff7b72-Tff7b72>Te6edf3textTb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tb4b4b4}
Te6edf3idx Tff7b72= Tb4b4b4(Te6edf3idx Tff7b72+ T79c0ff1Tb4b4b4) Tff7b72% Te6edf3MAX_UNSYNCED_POSTSTb4b4b4; T8b949e// wrap to start of cyclic queue
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffloop - skipping busy (or evicted) client %02XTa5d6ff"Tb4b4b4, Tb4b4b4(Tffa657uint32_tTb4b4b4)Te6edf3clientTff7b72-Tff7b72>Te6edf3idTb4b4b4.Te6edf3pub_keyTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3next_client_idx Tff7b72= Tb4b4b4(Te6edf3next_client_idx Tff7b72+ T79c0ff1Tb4b4b4) Tff7b72% Te6edf3aclTb4b4b4.Te6edf3getNumClientsTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// round robin polling for each client

Tff7b72if Tb4b4b4(Te6edf3did_pushTb4b4b4) Tb4b4b4{
Te6edf3next_push Tff7b72= Te6edf3futureMillisTb4b4b4(Te6edf3SYNC_PUSH_INTERVALTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// were no unsynced posts for curr client, so process next client much quicker! (in next loop())
Te6edf3next_push Tff7b72= Te6edf3futureMillisTb4b4b4(Te6edf3SYNC_PUSH_INTERVAL Tff7b72/ T79c0ff8Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3next_flood_advert Tff7b72&Tff7b72& Te6edf3millisHasNowPassedTb4b4b4(Te6edf3next_flood_advertTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3pkt Tff7b72= Te6edf3createSelfAdvertTb4b4b4(Tb4b4b4)Tb4b4b4;
Tffa657uint32_t Te6edf3delay_millis Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pktTb4b4b4) Te6edf3sendFloodScopedTb4b4b4(Te6edf3default_scopeTb4b4b4, Te6edf3pktTb4b4b4, Te6edf3delay_millisTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3path_hash_mode Tff7b72+ T79c0ff1Tb4b4b4)Tb4b4b4;

Te6edf3updateFloodAdvertTimerTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// schedule next flood advert
Te6edf3updateAdvertTimerTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// also schedule local advert (so they don't overlap)
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3next_local_advert Tff7b72&Tff7b72& Te6edf3millisHasNowPassedTb4b4b4(Te6edf3next_local_advertTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3meshTff7b72:Tff7b72:Te6edf3Packet Tff7b72*Te6edf3pkt Tff7b72= Te6edf3createSelfAdvertTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pktTb4b4b4) Te6edf3sendZeroHopTb4b4b4(Te6edf3pktTb4b4b4)Tb4b4b4;

Te6edf3updateAdvertTimerTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// schedule next local advert
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3set_radio_at Tff7b72&Tff7b72& Te6edf3millisHasNowPassedTb4b4b4(Te6edf3set_radio_atTb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// apply pending (temporary) radio params
Te6edf3set_radio_at Tff7b72= T79c0ff0Tb4b4b4; T8b949e// clear timer
Te6edf3radio_driverTb4b4b4.Te6edf3setParamsTb4b4b4(Te6edf3pending_freqTb4b4b4, Te6edf3pending_bwTb4b4b4, Te6edf3pending_sfTb4b4b4, Te6edf3pending_crTb4b4b4)Tb4b4b4;
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffTemp radio paramsTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3revert_radio_at Tff7b72&Tff7b72& Te6edf3millisHasNowPassedTb4b4b4(Te6edf3revert_radio_atTb4b4b4)Tb4b4b4) Tb4b4b4{ T8b949e// revert radio params to orig
Te6edf3revert_radio_at Tff7b72= T79c0ff0Tb4b4b4; T8b949e// clear timer
Te6edf3radio_driverTb4b4b4.Te6edf3setParamsTb4b4b4(Te6edf3_prefsTb4b4b4.Te6edf3freqTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3bwTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3sfTb4b4b4, Te6edf3_prefsTb4b4b4.Te6edf3crTb4b4b4)Tb4b4b4;
Te6edf3MESH_DEBUG_PRINTLNTb4b4b4(Ta5d6ff"Ta5d6ffRadio params restoredTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// is pending dirty contacts write needed?
Tff7b72if Tb4b4b4(Te6edf3dirty_contacts_expiry Tff7b72&Tff7b72& Te6edf3millisHasNowPassedTb4b4b4(Te6edf3dirty_contacts_expiryTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3aclTb4b4b4.Te6edf3saveTb4b4b4(Te6edf3_fsTb4b4b4, Te6edf3MyMeshTff7b72:Tff7b72:Te6edf3saveFilterTb4b4b4)Tb4b4b4;
Te6edf3dirty_contacts_expiry Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}

T8b949e// TODO: periodically check for OLD/inactive entries in known_clients[], and evict

T8b949e// update uptime
Tffa657uint32_t Te6edf3now Tff7b72= Te6edf3millisTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3uptime_millis Tff7b72+Tff7b72= Te6edf3now Tff7b72- Te6edf3last_millisTb4b4b4;
Te6edf3last_millis Tff7b72= Te6edf3nowTb4b4b4;
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.44s